Closed k0ekk0ek closed 5 months ago
The buffer overflows should be trivially detected by compiling with address sanitizers, which you can do in CI. We do it for simdjson and other projects of mine.
A comment by a colleague to look into.
Something that is maybe hard to find, but now that I'm looking at the hex and b64 encoders, is that the
"0"
string may be used to denote a a zero length rdata field. For theNSEC3
salt that's-
for the zero length salt field. This is possibly something from dnssec-bis-updates
Support for enabling sanitizers was already available in the CMakeLists.txt
. I've enabled it in #166.
9u > ..
but earlier the check is for 10u > ..
for similar loop code in parse_longitude and parse_latitude. There are no '9' characters in the altitude?aa
, then both the comparisons with '0' and 'X' are false, and 0^0 is 0, so it allows that sequence. But I guess it should reject it, because then it skips it with data+=2
later.rdata->octets
output one line later, it copies number twice.parser->file->buffer.data + parser->file.buffer.index
, perhaps use realloc(parser->file->buffer.data, ..)
.maybe_take_quoted
has length without -1, but other quoted token length has delimiters.head-fields.head-1
. It sets data++
allright."key"
.<=
to find equal items, also at 702. It is <=
at line 962.<=
comparison. Also in src/westmere/type.h:80.TYPE0
is used for debug set ups, so it should be valid to encounter, in a type bitmap, or as unknown RR type.!window != !last_window
when it reads type 300, since the current window is 1 and the last is 0, the inversion is 0 != 1
and it rejects this? It may also be useful to reject duplicates, window == last_window
. It may also be useful to reject blocks == 0
, the empty NSEC has no windows.f[3]
to f[0]
.o, n
instead of o+c, n-c
.NAME(&f[n!=0])
.break;
after this case, it cannot fall through to allow a name.char - '0'
value. Line 251 has working assignment to digit.file->name
is NULL
, and file->path
is not_a_file
, it attempts to free not_a_file
after string parse.size
is too small by roughly the length of the tests[i].timestamp
string.This finished the review, the code looks nice! The speed up in zone parsing is very nice for large datasets.
Nr. 44. is now fixed by the commit that fixes the comparison to use file->path
. So it no longer attempts to free not_a_file
.
Nr 32. not entirely correct. It only enters the loop if key <= highest_key
(so at least one key has been read). If it then detects the key is duplicate, the message is correct because there's indeed a duplicate key. I check for automatically mandatory keys after parsing the list.
You are right because of that it works to detect key 0, because there is always at least one key already read. There is then still the other parts about not always finding equal keys, or about the difference in code lines: line 601 if (key < smaller_key)
, line 695 if (key < smaller_key)
and line 965 if (key <= smaller_key)
.
That was just fixed in the commit just now, the difference in code lines.
I've updated the documentation about "reading past the buffer" in #169. It's not nearly enough to properly explain, but it basically comes down to the scanner guaranteeing only complete tokens are returned. We really don't want to concern the parser with having to deal with partial tokens or anything like that. The input is also always padded with 64-bytes. Combining those two facts, a lot of parsers trust that while they read a character that is part of the contiguous set of characters the next one is either part of that set or a delimiter. For example, if I'm reading an escaped sequence, as long as I'm reading digits it cannot be a delimiter (either for quoted or contiguous) and since the input is guaranteed to be padded I'm save in reading the data. It may be worthwile changing this for the fallback implementation eventually though (see #174)
@wcawijngaards is reviewing
main
. A summary of his comments so-far:src/westmere/bits.h:37 prefix_xor references avx2 in the comment, but that is haswell.In check_sshfp_rdata, c>=n, should that not error on c==n ?compat/getopt.h:2, there is placeholder text in 'some useful comment'.include/zone/attributes.h:31 the text is duplicated at line 20, up to line 40, for has_attribute.include/zone.h:208 in some places there are 'FIXME' comments.For a compile on mingw crosscompiler, change src/generic/endian.h #if _MSC_VER to #if _WIN32 .(fixed by #168).In src/zone.c change Windows.h to windows.h. It can then also link in crosscompile.zone-bench
links with -lshlwapi added, -lssp, but withoutcompat/getopt.c
that is not needed for the croscompile.src/generic/wks.h:254 That returns -1 for a failure, but in src/generic/types.h:432 it only checks for true and false. When it returns -1, the variable port is undefined.src/fallback/name.h:51 if (t != te || w >= we). If that is w>we, then it would allow length 255, and that is a length that should be allowed?src/fallback/scanner.h:49 parser->file->lines.tail[0] -= *end == '\n'; . This dereferences the end pointer, buf that is one past the end of the buffer, and not allowed? Also at line 73.(see comment about padded operation below)src/fallback/text.h:22 d[2] = (uint8_t)text[3] - '0'; the routines that call unescape, and also there, it does not check for the availability of the next two bytes in the buffer. After the read beyond end of buffer, it flags it as a parse error.(see comment about padded operation below)src/generic/apl.h, dereferences text without check of length.(see comment about padded operation below) (apl requires contiguous tokens, so it has a length of at least one)in src/generic/cert.h:94 The second '&' is not needed.Also the input&= is in src/generic/dnssec.h:135.src/generic/eui:43 eui_base16_dec_loop_generic_32_inner(input+12, rdata->octets+4, 1)) This calls at position 12, but s[5] is then input[17] and that is one past the end of the buffer. Also wouldn't input that is like 'xx+xx+xx-xx-xx-xx' and with dash at 0, cause the comparison to do 0^0^0, is 0 and not fail to reject the invalid syntax.src/generic/parser.h:274fread
fills complete buffer while variable was just increased to previous +ZONE_WINDOW_SIZE
, probably an error.tempnam' is dangerous, better use 'mkstemp'
. Unbound usessnprintf(buf, sizeof(buf), "/tmp/unbound.unittest.%u.%d", (unsigned)getpid(), i);
, which compiles without warnings. Code checkers will fall over this, again and again. It is therefore preferred not to use these kinds of functions.No error is printed when the$INCLUDE
directive references a non-existing file(?)