Re: BUG #19583: macaddr input accepts octet fields longer than 8 hex digits

From: Zexin Li <lizi(dot)openmind(at)gmail(dot)com>
To: daniel(at)yesql(dot)se
Cc: malis(at)pgrust(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #19583: macaddr input accepts octet fields longer than 8 hex digits
Date: 2026-08-16 23:36:01
Message-ID: CAAP6ZkQbENMVG7jcUbNyFyZLcNinJ7kzWjARXs0pVwsfmVk+pg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

On Aug 4, 2026, Zexin Li wrote:
> For the problem at hand I lean towards (b), since it removes the
> undefined behavior instead of relocating it, but (a) is the smaller
> change and I'd be fine with either.

I tried implementing (b); patch attached.

The colon- and dash-separated formats are now parsed by a small
helper that reads each field with strtol() and hands the six values
to the existing 0..255 range check. The five condensed %2x formats
are untouched. Since %x is defined in terms of strtoul()'s subject
sequence, strtol() accepts the same field syntax, so the forms v1
rejected as a side effect are still accepted this time. Each line
shows the old behavior, then the new one:

'001:00:2b:01:02:03': accepted; unchanged
'0x1:00:2b:01:02:03': accepted; unchanged
'+f:00:2b:01:02:03': accepted; unchanged
'a:b:c:d:e:f': accepted; unchanged
'aa: bb:cc:dd:ee:ff': accepted; unchanged
'1ff:0:0:0:0:0': octet error (22003); unchanged
'-f:0:0:0:0:0': octet error (22003); unchanged
'100000001:0:0:0:0:0': stored 01:00:00:00:00:00; now the octet error
'-ffffff01:0:0:0:0:0': stored ff:00:00:00:00:00; now the octet error
'0x:00:2b:01:02:03': accepted on glibc; now the syntax error (22P02)

A field whose value does not fit an octet now reliably draws the
existing "invalid octet value" error, the same one '1ff:...' gets
today; both error texts stay as they are. No errno check is needed:
for such a field, strtol() returns either the exact value (when it
fits in a long) or LONG_MIN/LONG_MAX (when it does not), and both
fail the existing range check. This follows what
from_char_parse_int_len() in formatting.c does, parsing with
strtol() and range-checking the result. I used strtol() rather than
strtoul() so that a negative field is still seen as a negative
value by the (a < 0) half of the existing check, as before.

The remaining difference is the bare-'0x' case from my previous
mail: a '0x' field with no hex digit after it, which glibc's sscanf
read as zero while strtol() stops at the '0' (that acceptance
already varied by platform). The two rewritten formats no longer
accept such a field; that part is strtol()'s standard
subject-sequence behavior, not a glibc detail. What happens to the
input then depends on the unchanged condensed templates: most such
inputs draw the syntax error ('0x:00:2b:01:02:03' above); on glibc,
a few dash-separated ones still match a condensed template and
either draw the octet error ('0x-1-0-0-0-0') or stay accepted with
the same stored value ('0x-0-0-0-0-0'); and ones that used to fail
the octet check, like '0x:1ff:0:0:0:0', draw the syntax error now.
I documented this in the commit message rather than try to unify
the outcomes, which would have meant touching the condensed
templates too.

I also compared the old and the new parsing with a differential
harness over about 3.7 million generated inputs (field shapes x
separators x whitespace placements, plus random strings). The only
divergences are the fields that used to wrap, now rejected, and the
bare-'0x' class above; no input is newly accepted, and no accepted
input changes its stored value.

Besides the rejection cases, which fail without the code change,
the added regression tests also pin the accepted forms, so a later
change that stops accepting one of them would show up.

I'd appreciate any feedback.

Best regards,
Zexin Li

Attachment Content-Type Size
v2-0001-Reject-out-of-range-octets-in-macaddr-input.patch application/octet-stream 12.6 KB

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Zexin Li 2026-08-17 03:23:10 Re: BUG #19598: pg_waldump: -s/-e accept out-of-range WAL locations and silently use the low 32 bits
Previous Message Michael Paquier 2026-08-16 22:26:26 Re: BUG #19612: SEGV in ParseConfigFp() in guc-file.l