Tom Lane <[email protected]> writes:
> Oh, that's an excellent point: if we did want to go the direction of
> exposing strtol's full behavior, we'd need to make the code check
> that strtol ate the whole input, which it does not today.  I think
> it's unnecessary to add such a check if we switch to base 10
> (maybe I'm wrong?).

I think you're right, and I measured it rather than reason about it. I
instrumented the one strtol() call in _int_bool.c and swept every byte
0x01-0xFF in seven operand positions (SQL_ASCII, so high bytes arrive
unconverted): the only bytes that ever reach the buffer are '-' and '0'-'9',
the same under base 0 and base 10. Everything else -- x, b, o, e, '+', '_',
'.', and all of 0x80-0xFF -- is a syntax error before strtol() is called. So
strtol() is always handed an optional sign followed by decimal digits, and
under base 10 it consumes all of them; there is no trailing input for an "ate
the whole input" check to catch.

To put a number on it, I ran 72,222,250 operand buffers (the short ones
exhaustively, the longer ones sampled) through strtol() with an end-pointer
check. Under base 10 exactly one is not consumed whole: the lone "-", where
strtol() returns 0 and advances nothing, so '1&-' parses as '1 & 0'. Under
base 0, 23,620,854 of them are not -- every leading-zero operand that reaches
an 8 or 9, which is the bug. A cross-check against the instrumented server
matched on all 29,430 sampled buffers (buffer, endptr, value, errno and
output), so this is the server's behavior, not a model's.

Two things so "nothing left to guard" isn't overstated. The existing
errno/int32 range check still earns its keep: an overflowing operand like
'99999999999' is consumed whole and rejected there, not through endptr. And
the lone "-" is pre-existing and base-independent -- base 0 accepts it as 0
today too; an end-pointer check would reject it, but that is a separate
question from the base, so I would not fold it into this patch.

regards,
Manu


Reply via email to