Message ID | CAEfK_46hGYYpO4YhYcxdUar1ugLQwbpJMgxAJDJU13zSpbD4zw@mail.gmail.com |
---|---|
State | New |
Headers | show |
On Tue, May 02, 2017 at 10:32:40AM -0400, Doug Gale wrote: > + } else { > + /* decode repeat length */ > + int repeat = (unsigned char)ch - ' ' + 3; > + if (s->line_buf_index + repeat >= sizeof(s->line_buf) - 1) { > + /* that many repeats would overrun the command buffer */ > +#ifdef DEBUG_GDB > + printf("gdbstub command buffer overrun," > + " dropping command\n"); > +#endif > + s->state = RS_IDLE; > + } else if (s->line_buf_index <= 2) { Why s->line_buf_index <= 2? I expected s->line_buf_index < 1 since we just need 1 character to clone for run-length decoding. > + /* got a repeat but we have nothing to repeat */ > +#ifdef DEBUG_GDB > + printf("gdbstub got invalid RLE sequence\n"); > +#endif > + } else { Missing s->state = RS_IDLE?
[Oops, forgot to reply all, resending...] Yes, on second thought, <= 2 is off by one. [0] would be the '$', [1] would be the repeated character, and [2] would be the '*'. And yes, there is a missing s->state = RS_IDLE there. Good catch. I'll post updated patch shortly... On Fri, May 5, 2017 at 10:45 AM, Stefan Hajnoczi <stefanha@gmail.com> wrote: > On Tue, May 02, 2017 at 10:32:40AM -0400, Doug Gale wrote: >> + } else { >> + /* decode repeat length */ >> + int repeat = (unsigned char)ch - ' ' + 3; >> + if (s->line_buf_index + repeat >= sizeof(s->line_buf) - 1) { >> + /* that many repeats would overrun the command buffer */ >> +#ifdef DEBUG_GDB >> + printf("gdbstub command buffer overrun," >> + " dropping command\n"); >> +#endif >> + s->state = RS_IDLE; >> + } else if (s->line_buf_index <= 2) { > > Why s->line_buf_index <= 2? I expected s->line_buf_index < 1 since we > just need 1 character to clone for run-length decoding. > >> + /* got a repeat but we have nothing to repeat */ >> +#ifdef DEBUG_GDB >> + printf("gdbstub got invalid RLE sequence\n"); >> +#endif >> + } else { > > Missing s->state = RS_IDLE?
On Sun, May 7, 2017 at 4:26 PM, Doug Gale <doug16k@gmail.com> wrote: > On Fri, May 5, 2017 at 10:45 AM, Stefan Hajnoczi <stefanha@gmail.com> wrote: >> On Tue, May 02, 2017 at 10:32:40AM -0400, Doug Gale wrote: >>> + } else { >>> + /* decode repeat length */ >>> + int repeat = (unsigned char)ch - ' ' + 3; >>> + if (s->line_buf_index + repeat >= sizeof(s->line_buf) - 1) { >>> + /* that many repeats would overrun the command buffer */ >>> +#ifdef DEBUG_GDB >>> + printf("gdbstub command buffer overrun," >>> + " dropping command\n"); >>> +#endif >>> + s->state = RS_IDLE; >>> + } else if (s->line_buf_index <= 2) { >> >> Why s->line_buf_index <= 2? I expected s->line_buf_index < 1 since we >> just need 1 character to clone for run-length decoding. > > Yes, on second thought, <= 2 is off by one. [0] would be the '$', [1] > would be the repeated character, and [2] would be the '*'. '$' and '*' are not placed into line_buf[] and do not increment line_buf_index. They don't count. I think the correct condition is line_buf_index < 1 so that the following input from the GDB documentation parses: "$0* " -> "0000". https://sourceware.org/gdb/onlinedocs/gdb/Overview.html
diff --git a/gdbstub.c b/gdbstub.c index 9911153..d6f1b0e 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -286,6 +286,8 @@ enum RSState { RS_INACTIVE, RS_IDLE, RS_GETLINE, + RS_GETLINE_ESC, + RS_GETLINE_RLE, RS_CHKSUM1, RS_CHKSUM2, }; @@ -296,7 +298,8 @@ typedef struct GDBState { enum RSState state; /* parsing state */ char line_buf[MAX_PACKET_LENGTH]; int line_buf_index; - int line_csum; + int line_sum; /* running checksum */ + int line_csum; /* checksum at the end of the packet */ uint8_t last_packet[MAX_PACKET_LENGTH + 4]; int last_packet_len; int signal; @@ -1508,7 +1511,6 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) static void gdb_read_byte(GDBState *s, int ch) { - int i, csum; uint8_t reply;