fix(parser): reject malformed MAC inputs and make print helpers banked

parse_mac now accepts only a strict aa:bb:cc:dd:ee:ff (or '-' separators)
form: each octet is exactly two hex digits, the 5 separators are a single
consistent character, and nothing is allowed after the 6th octet. This
rejects the malformed values the reviewer flagged (repeated separators,
missing digits, trailing characters). A new inline hexval() helper does the
digit-to-value conversion and can be reused by future commands.

print_mac and print_ip are marked __banked to match cmd_parser(), which
lives in codeseg BANK2 and is itself __banked, so callers across the code
bank work correctly. cmd_parser.h is updated with the new prototypes and
the __banked qualifier on print_ip.

Verified with make MACHINE=KP_9000_9XHML_X_V3_1: the build links cleanly
and the internal-RAM (DSEG) layout is unchanged against main; XSEG is
unchanged and ROM grows by 184 bytes. A host-side test confirms parse_mac
rejects the two malformed inputs from the review.
This commit is contained in:
gnacho committed 2026-09-10 00:14:58 +02:00
1 parent 6616a0c9ce
commit dc4fb5becc
2 files changed
+45 -25

No files matched your search

+42 -24
View File
@@ -106,6 +106,18 @@ inline uint8_t isnumber(uint8_t l)
return (l <= ('9'-'0'));
}
/* Converts a single ASCII hex digit to its value, or 0xff if it is not a valid
* hex digit. Accepts '0'-'9', 'a'-'f' and 'A'-'F'. */
inline uint8_t hexval(uint8_t c)
{
if (isnumber(c))
return c - '0';
c |= 0x20;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return 0xff;
}
uint8_t cmd_compare(uint8_t start, __code uint8_t * cmd)
{
@@ -349,7 +361,7 @@ err:
}
// Prints an IPv4 address.
void print_ip(__xdata uint8_t * ptr)
void print_ip(__xdata uint8_t * ptr) __banked
{
uint8_t idx = 0;
uint8_t num;
@@ -365,7 +377,7 @@ void print_ip(__xdata uint8_t * ptr)
}
// Prints a MAC address.
void print_mac(__xdata uint8_t *ptr)
void print_mac(__xdata uint8_t *ptr) __banked
{
uint8_t idx = 0;
uint8_t num;
@@ -380,38 +392,44 @@ void print_mac(__xdata uint8_t *ptr)
}
}
// Parses a MAC address (12 hex digits, ':' or '-' separators optional) from
// cmd_buffer starting at idx into mac[6]. Returns the number of bytes
// consumed, or 0 on error.
// Parses a strict MAC address "aa:bb:cc:dd:ee:ff" (or "-" separators) from
// cmd_buffer starting at idx into mac[6]. Each of the 6 octets must be exactly
// two hex digits and the 5 separators must be the same single character, so
// malformed input like repeated separators ("aa::bb"), missing digits or a
// trailing hex digit ("aa:bb:cc:dd:ee:ff:0") is rejected. Returns the number of
// bytes consumed, or 0 on error.
uint8_t parse_mac(uint8_t idx, __xdata uint8_t *mac)
{
uint8_t sep = 0;
uint8_t b = 0;
uint8_t hi = 0xff; /* 0xff = waiting for the high nibble */
uint8_t c;
uint8_t hi;
uint8_t lo;
while (b < 6) {
hi = hexval(cmd_buffer[idx++]);
lo = hexval(cmd_buffer[idx++]);
if (hi == 0xff || lo == 0xff)
return 0;
mac[b++] = (hi << 4) | lo;
if (b == 6)
break;
c = cmd_buffer[idx];
if (c == NUL || c == ' ' || c == '\r' || c == '\n')
break;
if (c != ':' && c != '-')
return 0;
if (sep == 0)
sep = c;
else if (c != sep)
return 0;
idx++;
if (c == ':' || c == '-')
continue;
c |= 0x20;
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'a' && c <= 'f')
c -= 'a' - 10;
else
break;
if (hi == 0xff) {
hi = c;
} else {
mac[b++] = (hi << 4) | c;
hi = 0xff;
}
}
if (b != 6 || hi != 0xff)
// No trailing characters: the next byte must be a separator-like EOF.
c = cmd_buffer[idx];
if (c != NUL && c != ' ')
return 0;
return idx;
}
+3 -1
View File
@@ -13,7 +13,9 @@ void cmd_tokenize(void) __banked;
void cmd_parser(void) __banked;
void execute_config(void) __banked;
void execute_commands(__xdata uint8_t *p) __banked;
void print_ip(__xdata uint8_t *ptr);
void print_ip(__xdata uint8_t *ptr) __banked;
void print_mac(__xdata uint8_t *ptr) __banked;
uint8_t parse_mac(uint8_t idx, __xdata uint8_t *mac);
void print_sw_version(void) __banked;
void clear_command_history(void) __banked;