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
