mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Rename --nul-output to --raw-output0, abort on string containing NUL
The option naming --nul-output was confusing, especially when we have a similar option for input stream in the future (--nul-input vs --null-input). Based on the observation of other command line tools, we rename the option to --raw-output0. We also drop the short option -0 to avoid confusion on introducing the NUL-delimited input option. Unlike the other command line tools outputting file names with NUL delimiter, jq deals with JSON, and its strings may contain NUL character. To protect users from the risk of injection attacks, we abort the program and print an error message before outputting strings including NUL character. Closes #2683.
This commit is contained in:
@@ -136,14 +136,15 @@ sections:
|
||||
formatted as a JSON string with quotes. This can be useful for
|
||||
making jq filters talk to non-JSON-based systems.
|
||||
|
||||
* `--join-output` / `-j`:
|
||||
|
||||
Like `-r` but jq won't print a newline after each output.
|
||||
|
||||
* `--nul-output` / `-0`:
|
||||
* `--raw-output0`:
|
||||
|
||||
Like `-r` but jq will print NUL instead of newline after each output.
|
||||
This can be useful when the values being output can contain newlines.
|
||||
When the output value contains NUL, jq exits with non-zero code.
|
||||
|
||||
* `--join-output` / `-j`:
|
||||
|
||||
Like `-r` but jq won't print a newline after each output.
|
||||
|
||||
* `--ascii-output` / `-a`:
|
||||
|
||||
|
12
jq.1.prebuilt
generated
12
jq.1.prebuilt
generated
@@ -82,18 +82,18 @@ By default, jq pretty\-prints JSON output\. Using this option will result in mor
|
||||
With this option, if the filter\'s result is a string then it will be written directly to standard output rather than being formatted as a JSON string with quotes\. This can be useful for making jq filters talk to non\-JSON\-based systems\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-raw\-output0\fR:
|
||||
.
|
||||
.IP
|
||||
Like \fB\-r\fR but jq will print NUL instead of newline after each output\. This can be useful when the values being output can contain newlines\. When the output value contains NUL, jq exits with non\-zero code\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-join\-output\fR / \fB\-j\fR:
|
||||
.
|
||||
.IP
|
||||
Like \fB\-r\fR but jq won\'t print a newline after each output\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-nul\-output\fR / \fB\-0\fR:
|
||||
.
|
||||
.IP
|
||||
Like \fB\-r\fR but jq will print NUL instead of newline after each output\. This can be useful when the values being output can contain newlines\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-ascii\-output\fR / \fB\-a\fR:
|
||||
.
|
||||
.IP
|
||||
|
32
src/main.c
32
src/main.c
@@ -74,8 +74,8 @@ static void usage(int code, int keep_it_short) {
|
||||
" -s, --slurp read all inputs into an array and use it as the single input value;\n"
|
||||
" -c, --compact-output compact instead of pretty-printed output;\n"
|
||||
" -r, --raw-output output strings directly without escapes and quotes;\n"
|
||||
" --raw-output0 implies -r and output NUL after each output;\n"
|
||||
" -j, --join-output implies -r and output without newline after each output;\n"
|
||||
" -0, --nul-output implies -r and output NUL after each output;\n"
|
||||
" -a, --ascii-output output strings by only ASCII characters using escape sequences;\n"
|
||||
" -S, --sort-keys sort keys of each object on output;\n"
|
||||
" -C, --color-output colorize JSON output;\n"
|
||||
@@ -111,11 +111,8 @@ static void die() {
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int isoptish(const char* text) {
|
||||
return text[0] == '-' && (text[1] == '-' || isalpha(text[1]) || text[1] == '0');
|
||||
return text[0] == '-' && (text[1] == '-' || isalpha(text[1]));
|
||||
}
|
||||
|
||||
static int isoption(const char* text, char shortopt, const char* longopt, size_t *short_opts) {
|
||||
@@ -141,7 +138,7 @@ enum {
|
||||
RAW_INPUT = 2,
|
||||
PROVIDE_NULL = 4,
|
||||
RAW_OUTPUT = 8,
|
||||
RAW_NUL = 16,
|
||||
RAW_OUTPUT0 = 16,
|
||||
ASCII_OUTPUT = 32,
|
||||
COLOR_OUTPUT = 64,
|
||||
NO_COLOR_OUTPUT = 128,
|
||||
@@ -191,6 +188,11 @@ static int process(jq_state *jq, jv value, int flags, int dumpopts, int options)
|
||||
if ((options & RAW_OUTPUT) && jv_get_kind(result) == JV_KIND_STRING) {
|
||||
if (options & ASCII_OUTPUT) {
|
||||
jv_dumpf(jv_copy(result), stdout, JV_PRINT_ASCII);
|
||||
} else if ((options & RAW_OUTPUT0) && strlen(jv_string_value(result)) != (unsigned long)jv_string_length_bytes(jv_copy(result))) {
|
||||
jv_free(result);
|
||||
result = jv_invalid_with_msg(jv_string(
|
||||
"Cannot dump a string containing NUL with --raw-output0 option"));
|
||||
break;
|
||||
} else {
|
||||
priv_fwrite(jv_string_value(result), jv_string_length_bytes(jv_copy(result)),
|
||||
stdout, dumpopts & JV_PRINT_ISATTY);
|
||||
@@ -208,7 +210,7 @@ static int process(jq_state *jq, jv value, int flags, int dumpopts, int options)
|
||||
}
|
||||
if (!(options & RAW_NO_LF))
|
||||
priv_fwrite("\n", 1, stdout, dumpopts & JV_PRINT_ISATTY);
|
||||
if (options & RAW_NUL)
|
||||
if (options & RAW_OUTPUT0)
|
||||
priv_fwrite("\0", 1, stdout, dumpopts & JV_PRINT_ISATTY);
|
||||
if (options & UNBUFFERED_OUTPUT)
|
||||
fflush(stdout);
|
||||
@@ -394,6 +396,14 @@ int main(int argc, char* argv[]) {
|
||||
options |= RAW_OUTPUT;
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "raw-output0", &short_opts)) {
|
||||
options |= RAW_OUTPUT | RAW_NO_LF | RAW_OUTPUT0;
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
if (isoption(argv[i], 'j', "join-output", &short_opts)) {
|
||||
options |= RAW_OUTPUT | RAW_NO_LF;
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
if (isoption(argv[i], 'c', "compact-output", &short_opts)) {
|
||||
dumpopts &= ~(JV_PRINT_TAB | JV_PRINT_INDENT_FLAGS(7));
|
||||
if (!short_opts) continue;
|
||||
@@ -430,14 +440,6 @@ int main(int argc, char* argv[]) {
|
||||
options |= FROM_FILE;
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
if (isoption(argv[i], 'j', "join-output", &short_opts)) {
|
||||
options |= RAW_OUTPUT | RAW_NO_LF;
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
if (isoption(argv[i], '0', "nul-output", &short_opts)) {
|
||||
options |= RAW_OUTPUT | RAW_NO_LF | RAW_NUL;
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
if (isoption(argv[i], 'b', "binary", &short_opts)) {
|
||||
#ifdef WIN32
|
||||
fflush(stdout);
|
||||
|
16
tests/shtest
16
tests/shtest
@@ -165,12 +165,20 @@ cmp $d/out $d/expected
|
||||
printf "[1,2][3,4]\n" | $JQ -cs add > $d/out 2>&1
|
||||
cmp $d/out $d/expected
|
||||
|
||||
# Regression test for -0 / --nul-output
|
||||
# Regression test for --raw-output0
|
||||
printf "a\0b\0" > $d/expected
|
||||
printf '["a", "b"]' | $JQ -0 .[] > $d/out 2>&1
|
||||
cmp $d/out $d/expected
|
||||
printf '["a", "b"]' | $JQ --nul-output .[] > $d/out 2>&1
|
||||
printf '["a", "b"]' | $VALGRIND $Q $JQ --raw-output0 .[] > $d/out
|
||||
cmp $d/out $d/expected
|
||||
printf "a\0" > $d/expected
|
||||
if printf '["a", "c\\u0000d", "b"]' | $VALGRIND $Q $JQ --raw-output0 .[] > $d/out; then
|
||||
echo "Should exit error on string containing NUL with --raw-output0" 1>&2
|
||||
exit 1
|
||||
elif [ $? -ne 5 ]; then
|
||||
echo "Invalid error code" 1>&2
|
||||
exit 1
|
||||
else
|
||||
cmp $d/out $d/expected
|
||||
fi
|
||||
|
||||
## Test streaming parser
|
||||
|
||||
|
Reference in New Issue
Block a user