summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMuh Muhten <muh.muhten@gmail.com>2019-02-07 01:53:09 -0500
committerNico Williams <nico@cryptonector.com>2019-02-20 20:12:52 -0600
commit85caac44733919105980764a4033bbfdf3a8b77c (patch)
treee94cc6ef6187cfb79d1e6b694df666219cb27cdb
parent048acee39babe759d1db0f32f263857c27361746 (diff)
Work around fgets()'s lack of length reporting
Stop losing \0s from the end of files because we don't know how much fgets() read into our buffer. If we prefill the buffer with anything other than zeroes, we can actually tell the difference between the terminator and unused space in the buffer. This is possibly more expensive, but at least it should be correct. Fixes #1504
-rw-r--r--src/util.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/src/util.c b/src/util.c
index df839520..99d6020a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -309,7 +309,7 @@ static int jq_util_input_read_more(jq_util_input_state *state) {
state->buf_valid_len = 0;
if (state->current_input) {
char *res;
- memset(state->buf, 0, sizeof(state->buf));
+ memset(state->buf, 0xff, sizeof(state->buf));
while (!(res = fgets(state->buf, sizeof(state->buf), state->current_input)) &&
ferror(state->current_input) && errno == EINTR)
@@ -334,20 +334,22 @@ static int jq_util_input_read_more(jq_util_input_state *state) {
size_t i;
/*
- * XXX We can't know how many bytes we've read!
+ * XXX We don't know how many bytes we've read!
*
* We can't use getline() because there need not be any newlines
* in the input. The only entirely correct choices are: use
* fgetc() or fread(). Using fread() will complicate buffer
* management here.
*
- * For now we guess how much fgets() read.
+ * For now we check how much fgets() read by scanning backwards for the
+ * terminating '\0'. This only works because we previously memset our
+ * buffer with something nonzero.
*/
- for (p = state->buf, i = 0; i < sizeof(state->buf); i++) {
- if (state->buf[i] != '\0')
- p = &state->buf[i];
+ for (p = state->buf, i = sizeof(state->buf) - 1; i > 0; i--) {
+ if (state->buf[i] == '\0')
+ break;
}
- state->buf_valid_len = p - state->buf + 1;
+ state->buf_valid_len = i;
} else if (p == NULL) {
state->buf_valid_len = sizeof(state->buf) - 1;
} else {