如何将用户输入净化为有效的 C 字符串文字?
How can I sanitize user input into valid C-String literals?
我正在尝试使用 shell 脚本生成用于包装可执行文件的 C 代码。
这需要在 Linux 和 MacOS 上工作,并且依赖性尽可能少。我不关心 Windows(除了 WSL2)
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
putenv("X=1");
putenv("HELLO=WORLD")
argv[0] = "/usr/bin/python3";
return execv("/usr/bin/python3", argv);
}
天真的方法:
# make-c-wrapper.sh EXECUTABLE ARGS
#
# ARGS:
# --argv0 NAME : set name of executed process to NAME
# (defaults to EXECUTABLE)
# --set VAR VAL : add VAR with value VAL to the executable’s
# environment
echo "#include <unistd.h>\n#include <stdlib.h>\n\nint main(int argc, char **argv) {"
executable=""
params=("$@")
for ((n = 1; n < ${#params[*]}; n += 1)); do
p="${params[$n]}"
if [[ "$p" == "--set" ]]; then
key="${params[$((n + 1))]}"
value="${params[$((n + 2))]}"
n=$((n + 2))
echo " putenv(\"$key=$value\");"
elif [[ "$p" == "--argv0" ]]; then
argv0="${params[$((n + 1))]}"
n=$((n + 1))
else
# Using an error macro, we will make sure the compiler gives an understandable error message
echo " #error make-c-wrapper.sh did not understand argument $p"
fi
done
echo " argv[0] = \"${argv0:-$executable}\";\n return execv(\"$executable\", argv);\n}"
但是,如果您尝试在输入中提供特殊字符,则会失败:
./make-c-wrapper /usr/bin/python3 --set "Hello" "This is\"\na test"
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
putenv("Hello=This is"
a test");
argv[0] = "/usr/bin/python3";
return execv("/usr/bin/python3", argv);
}
我希望在这里看到的是:
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
putenv("Hello=This is\"\na test");
argv[0] = "/usr/bin/python3";
return execv("/usr/bin/python3", argv);
}
根据这个答案:,似乎我需要转义以下字符以确保结果是有效的 C 字符串文字:"
、\
、 \r
、\n
、[=19=]
和 \?
.
有没有简单的方法来做到这一点?它需要在 MacOS 上运行,而不仅仅是 Linux.
it seems like I need to escape the following characters to make sure the result is a valid C string literal: "
, \
, \r
, \n
, [=16=]
and \?
.
您需要转义 "
、\
和换行符。当你这样做的时候,逃避马车 return 是有意义的。虽然 ?
有一个转义序列,但该字符也可以代表它自己。输入中的空字符不能表示为字符串文字的元素,并且您的 shell 可能也不会在变量值中处理它们,因此您最好不要对它们给予任何特殊考虑。
Shell 参数扩展语法具有子字符串替换功能和您可以利用的类 C 文字语法。 shell 引用有点复杂,但是例如,这个 ...
escape_string_literal() {
result=${1//'\'/'\'}
result=${result//\"/'\"'}
result=${result//$'\n'/'\n'}
result=${result//$'\r'/'\r'}
}
escape_string_literal '"boo\"'
echo "${result}"
...打印
\"boo\\"
但是请注意,您不一定清楚在字符串文字中包含所有其他字符。特别是,即使其中大多数没有单字符转义符,其他控制字符也可能会或可能不会被接受为文字字符,具体取决于您的 C 实现。
我正在尝试使用 shell 脚本生成用于包装可执行文件的 C 代码。
这需要在 Linux 和 MacOS 上工作,并且依赖性尽可能少。我不关心 Windows(除了 WSL2)
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
putenv("X=1");
putenv("HELLO=WORLD")
argv[0] = "/usr/bin/python3";
return execv("/usr/bin/python3", argv);
}
天真的方法:
# make-c-wrapper.sh EXECUTABLE ARGS
#
# ARGS:
# --argv0 NAME : set name of executed process to NAME
# (defaults to EXECUTABLE)
# --set VAR VAL : add VAR with value VAL to the executable’s
# environment
echo "#include <unistd.h>\n#include <stdlib.h>\n\nint main(int argc, char **argv) {"
executable=""
params=("$@")
for ((n = 1; n < ${#params[*]}; n += 1)); do
p="${params[$n]}"
if [[ "$p" == "--set" ]]; then
key="${params[$((n + 1))]}"
value="${params[$((n + 2))]}"
n=$((n + 2))
echo " putenv(\"$key=$value\");"
elif [[ "$p" == "--argv0" ]]; then
argv0="${params[$((n + 1))]}"
n=$((n + 1))
else
# Using an error macro, we will make sure the compiler gives an understandable error message
echo " #error make-c-wrapper.sh did not understand argument $p"
fi
done
echo " argv[0] = \"${argv0:-$executable}\";\n return execv(\"$executable\", argv);\n}"
但是,如果您尝试在输入中提供特殊字符,则会失败:
./make-c-wrapper /usr/bin/python3 --set "Hello" "This is\"\na test"
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
putenv("Hello=This is"
a test");
argv[0] = "/usr/bin/python3";
return execv("/usr/bin/python3", argv);
}
我希望在这里看到的是:
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
putenv("Hello=This is\"\na test");
argv[0] = "/usr/bin/python3";
return execv("/usr/bin/python3", argv);
}
根据这个答案:,似乎我需要转义以下字符以确保结果是有效的 C 字符串文字:"
、\
、 \r
、\n
、[=19=]
和 \?
.
有没有简单的方法来做到这一点?它需要在 MacOS 上运行,而不仅仅是 Linux.
it seems like I need to escape the following characters to make sure the result is a valid C string literal:
"
,\
,\r
,\n
,[=16=]
and\?
.
您需要转义 "
、\
和换行符。当你这样做的时候,逃避马车 return 是有意义的。虽然 ?
有一个转义序列,但该字符也可以代表它自己。输入中的空字符不能表示为字符串文字的元素,并且您的 shell 可能也不会在变量值中处理它们,因此您最好不要对它们给予任何特殊考虑。
Shell 参数扩展语法具有子字符串替换功能和您可以利用的类 C 文字语法。 shell 引用有点复杂,但是例如,这个 ...
escape_string_literal() {
result=${1//'\'/'\'}
result=${result//\"/'\"'}
result=${result//$'\n'/'\n'}
result=${result//$'\r'/'\r'}
}
escape_string_literal '"boo\"'
echo "${result}"
...打印
\"boo\\"
但是请注意,您不一定清楚在字符串文字中包含所有其他字符。特别是,即使其中大多数没有单字符转义符,其他控制字符也可能会或可能不会被接受为文字字符,具体取决于您的 C 实现。