mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
vlan: bound the name table before writing into it
A VLAN name is copied into vlan_names with nothing checking vlan_ptr against VLAN_NAMES_SIZE. The only limit is the 128 byte command line, so enough named VLANs walk straight off the end of a 1 kB table. What sits immediately behind it makes this worse than a plain overflow: at 0x048A comes vlan_ptr itself, the index driving the write, then port_names and cmd_buffer. Once the index is corrupted the following writes land wherever it now points, and the configuration is replayed at boot, so a config file that overflows does it again on every start. Measure the name first and refuse it if the three id digits, the name, its separating space and the terminator would not fit. The check goes before vlan_name_remove() so a name that does not fit cannot take the existing one with it, and the VLAN still gets its ports: dropping the whole line would lose port membership during a config replay, which is worse than losing a name. The copy walks a pointer instead of indexing vlan_names[vlan_ptr++] each time, and the word offset comes out of cmd_words_b once. Writing the bound as VLAN_NAMES_SIZE - 5 folds the constant at compile time instead of adding it on every call. BANK2 ends up 25 bytes smaller than it was before the check existed.
This commit is contained in:
1 parent
5ecce86ef1
commit
1b514b5ea8
1 file changed
+19
-9
+19
-9
@@ -504,20 +504,30 @@ void parse_vlan(void)
|
||||
}
|
||||
|
||||
uint8_t w = 2;
|
||||
if (cmd_words_len > w && isletter(cmd_buffer[cmd_words_b[w]])) {
|
||||
uint8_t pos = cmd_words_b[w];
|
||||
if (cmd_words_len > w && isletter(cmd_buffer[pos])) {
|
||||
uint8_t i = 0;
|
||||
while (!cmd_is_space_or_nul(pos + i))
|
||||
i++;
|
||||
if (vlan_ptr + i > (VLAN_NAMES_SIZE - 5)) {
|
||||
print_string("VLAN name table full, name ignored\n");
|
||||
} else {
|
||||
vlan_name_remove(vlan_settings.vlan);
|
||||
vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 8) & 0xf];
|
||||
vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 4) & 0xf] ;
|
||||
vlan_names[vlan_ptr++] = hex[vlan_settings.vlan & 0xf];
|
||||
while(!cmd_is_space_or_nul(cmd_words_b[w] + i)) {
|
||||
write_char(cmd_buffer[cmd_words_b[w] + i]);
|
||||
vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++];
|
||||
__xdata uint8_t *vlan_str = &vlan_names[vlan_ptr];
|
||||
*vlan_str++ = hex[(vlan_settings.vlan >> 8) & 0xf];
|
||||
*vlan_str++ = hex[(vlan_settings.vlan >> 4) & 0xf] ;
|
||||
*vlan_str++ = hex[vlan_settings.vlan & 0xf];
|
||||
while(!cmd_is_space_or_nul(pos)) {
|
||||
uint8_t c = cmd_buffer[pos++];
|
||||
write_char(c);
|
||||
*vlan_str++ = c;
|
||||
}
|
||||
vlan_names[vlan_ptr++] = ' '; vlan_names[vlan_ptr] = NUL;
|
||||
w++;
|
||||
*vlan_str++ = ' '; *vlan_str = NUL;
|
||||
vlan_ptr = vlan_str - vlan_names;
|
||||
print_string("<\n");
|
||||
}
|
||||
w++;
|
||||
}
|
||||
|
||||
uint8_t ret;
|
||||
uint8_t idx;
|
||||
|
||||
Reference in new issue
Block a user