因为一个问题我很累: 我想运行一个bash脚本,自动创建另一个bash脚本,该脚本反过来应该已经包含C代码,它只是在其输出通过管道传输到播放时动态编译和运行。 我的示例基于ComputerPhile bitshift variations code。
我有一个像这样的C脚本(应该被替换并在以后开发):
g(i, x, t, o) {
return ((3 & x & (i * (
(3 & i >> 16 ? "BY}6YB6%" : "Qj}6jQ6%")[t%8] + 51
) >> o)) << 4);
};
main(i, n, s) {
for (i = 0; ;i++)
putchar(
g(i, 1, n = i >> 14, 12) +
g(i, s = i >> 17, n^i >> 13, 10) +
g(i, s/3, n + ((i >> 11) % 3), 10) +
g(i, s/5, 8 + n - ((i >> 10) % 3), 9)
);
}
我想
1.缩小它
2.将"
个字符转义为\"
得到这样的bash脚本:
#!/bin/bash
echo "g(i,x,t,o){return((3&x&(i*((3&i>>16?\"BY}6YB6%\":\"Qj}6jQ6%\")[t%8]+51)>>o))<<4);};main(i,n,s){for(i=0;;i++)putchar(g(i,1,n=i>>14,12)+g(i,s=i>>17,n^i>>13,10)+g(i,s/3,n+((i>>11)%3),10)+g(i,s/5,8+n-((i>>10)%3),9));}"|gcc -xc -&&./a.out|aplay
然而,我似乎无法接近那个目标。要么它会创建一个空字符串(echo ""|gcc ...
),要么奇怪地将脚本参数粘贴到(...return ((3 & x & (i c2sh.sh tmp waveform.c waveform.sh ( (3 & i >> 16 ? BY}6YB6%...
中,但我已经有一个版本,其中"
被正确替换了。< / p>
我的代码(没有清理,所以你可以看到我尝试的其他两件事)目前是:
#!/bin/bash
echo '#!/bin/bash' > tmp
out=''
echo $(cat waveform.c | tr '"' ' ')
#while read line; do
# out+="$line"
#done < 'waveform.c'
#out=$(echo $out | sed 's/"/\\"/g')
out=${out/"/\\"}
echo 'echo "'$out'" | gcc -xc -&& ./a.out | aplay' >> tmp
mv tmp 'waveform.sh'
chmod +x 'waveform.sh'
到底发生了什么,应该如何正确地完成?
答案 0 :(得分:3)
正确? 不应该完成。在bash中,代码生成是一种“气味”,与公认的最佳实践相反。
但是,无论如何你都要这样做,让shell进行转义,而不是试图编写自己的逻辑(几乎毫无例外地容易出现shell注入漏洞):
#!/bin/bash
infile=${1:-waveform.c} # read name from command-line argument if given
content=$(<"$infile") # $(<foo) is more efficient than $(cat foo)
content=${content//[[:space:]]/} # trim spaces from variable contents
# put the arguments to the command you want to generate into an array
cmd=( printf '%s\n' "$content" )
# tell the shell to generate a string which has each element of that array escaped
printf -v cmd_q '%q ' "${cmd[@]}"
# put our generated contents into an array, one line per each;
# not essential, but makes it easy to comment each line we generate below.
output=(
'#!/bin/bash' # using bash ensures that printf %q-generated code works.
"$cmd_q | gcc -xc - || exit" # use our generated string for all non-constant code.
'./a.out | aplay'
)
printf '%s\n' "${output[@]}" # finally, emit output with all of the above
注意事项:
printf '%q'
以这样的方式格式化给定的shell变量:当shell评估它时,它将评估回原始的文字内容。这不仅对于正确性而且对于安全性至关重要:如果您正在从别人的代码中听取波形,那么您不希望shell评估/* $(rm -rf ~) */
。echo
是一个非常模糊指定的命令,以便允许各种历史操作系统完全不同的实现符合the spec。正如POSIX建议的那样,在任何情况下,如果数据不是手工生成的,并且已知不会触发任何歧义,则应使用printf
。答案 1 :(得分:0)
GitHub上有一个有用的C Minifier * python脚本,minifier.py
,这可能有所帮助:
code=`python minifier.py waveform.c`
echo "$code" ## `printf "%s\n" "$code"` is safer though...
输出:
g(i,x,t,o){return((3&amp; x&amp;(i *((3&amp; i&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&n;&n;&n;&n;&n;&n;&n;&n;&n;&n;&n;&#;; &#34; QJ} 6jQ6%&#34;)[吨%8] 51)GT;&GT;○))≤;&LT; 4);};主(I,N,S){对于(I = 0 ;;我++)的putchar(按g(i,1,N =&GT;&GT; 14,12)+ G(I,S = I&GT;&GT; 17,N ^ I&GT;&GT; 13,10)+ G(ⅰ ,S / 3,N +((I&GT;&GT; 11)%3),10)+ G(I,S / 5,8 + N - ((I&GT;→10)%3),9));}
对于更一般的修复C. Duffy's answer引用每个字符, 100%增加,使用某种binary to hex encoding会更有效,尽管对人类毫无意义,例如:
python minifier.py waveform.c | base64
ZyhpLHgsdCxvKXtyZXR1cm4oKDMmeCYoaSooKDMmaT4+MTYgPyAiQll9NllCNiUiIDogIlFqfTZq
UTYlIilbdCU4XSs1MSk+Pm8pKTw8NCk7fTttYWluKGksbixzKXtmb3IoaT0wOztpKyspcHV0Y2hh
cihnKGksMSxuPWk+PjE0LDEyKStnKGkscz1pPj4xNyxuXmk+PjEzLDEwKStnKGkscy8zLG4rKChp
Pj4xMSklMyksMTApK2coaSxzLzUsOCtuLSgoaT4+MTApJTMpLDkpKTt9Cg==
这是不可读的,但是逃脱缩小的C ...