Browse Source

gdbstub: Fix misuse of isxdigit()

gdb_read_byte() passes its @ch argument to isxdigit().  Undefined
behavior when the value is negative.  Two callers:

* gdb_chr_receive() passes an uint8_t value.  Safe.

* gdb_handlesig() a char value.  Unsafe.  Not a security issue,
  because the characters come from the gdb client, which is trusted.

The obvious fix would be casting @ch to unsigned char.  But note that
gdb_read_byte() already casts @ch to uint8_t in many places.  Uses of
@ch without such a cast:

(1) Compare to a character constant with == or !=

(2) s->linesum += ch

(3) Store ch or ch ^ 0x20 into s->line_buf[]

(4) Check for invalid RLE count:
    ch < ' ' || ch == '#' || ch == '$' || ch > 126

(5) Pass to isxdigit()

(6) Pass to fromhex()

Change the parameter type from int to uint8_t, and drop the now
redundant casts.  Affects the above uses as follows:

(1) No change: the character constants are all non-negative.

(2) Effectively no change: we only ever use s->linesum & 0xff, and
    s->linesum is int.

(3) No change: s->line_buf[] is char[].

(4) No change.

(5) Avoid undefined behavior.

(6) No change: only reached when isxdigit(ch)

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <2019051418.16028-5-armbru@redhat.com>
master
Markus Armbruster 1 month ago
parent
commit
33c846efa2
1 changed files with 7 additions and 7 deletions
  1. 7
    7
      gdbstub.c

+ 7
- 7
gdbstub.c View File

@@ -1987,7 +1987,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
1987 1987
     va_end(va);
1988 1988
 }
1989 1989
 
1990
-static void gdb_read_byte(GDBState *s, int ch)
1990
+static void gdb_read_byte(GDBState *s, uint8_t ch)
1991 1991
 {
1992 1992
     uint8_t reply;
1993 1993
 
@@ -2001,7 +2001,7 @@ static void gdb_read_byte(GDBState *s, int ch)
2001 2001
         } else if (ch == '+') {
2002 2002
             trace_gdbstub_io_got_ack();
2003 2003
         } else {
2004
-            trace_gdbstub_io_got_unexpected((uint8_t)ch);
2004
+            trace_gdbstub_io_got_unexpected(ch);
2005 2005
         }
2006 2006
 
2007 2007
         if (ch == '+' || ch == '$')
@@ -2024,7 +2024,7 @@ static void gdb_read_byte(GDBState *s, int ch)
2024 2024
                 s->line_sum = 0;
2025 2025
                 s->state = RS_GETLINE;
2026 2026
             } else {
2027
-                trace_gdbstub_err_garbage((uint8_t)ch);
2027
+                trace_gdbstub_err_garbage(ch);
2028 2028
             }
2029 2029
             break;
2030 2030
         case RS_GETLINE:
@@ -2070,11 +2070,11 @@ static void gdb_read_byte(GDBState *s, int ch)
2070 2070
              */
2071 2071
             if (ch < ' ' || ch == '#' || ch == '$' || ch > 126) {
2072 2072
                 /* invalid RLE count encoding */
2073
-                trace_gdbstub_err_invalid_repeat((uint8_t)ch);
2073
+                trace_gdbstub_err_invalid_repeat(ch);
2074 2074
                 s->state = RS_GETLINE;
2075 2075
             } else {
2076 2076
                 /* decode repeat length */
2077
-                int repeat = (unsigned char)ch - ' ' + 3;
2077
+                int repeat = ch - ' ' + 3;
2078 2078
                 if (s->line_buf_index + repeat >= sizeof(s->line_buf) - 1) {
2079 2079
                     /* that many repeats would overrun the command buffer */
2080 2080
                     trace_gdbstub_err_overrun();
@@ -2096,7 +2096,7 @@ static void gdb_read_byte(GDBState *s, int ch)
2096 2096
         case RS_CHKSUM1:
2097 2097
             /* get high hex digit of checksum */
2098 2098
             if (!isxdigit(ch)) {
2099
-                trace_gdbstub_err_checksum_invalid((uint8_t)ch);
2099
+                trace_gdbstub_err_checksum_invalid(ch);
2100 2100
                 s->state = RS_GETLINE;
2101 2101
                 break;
2102 2102
             }
@@ -2107,7 +2107,7 @@ static void gdb_read_byte(GDBState *s, int ch)
2107 2107
         case RS_CHKSUM2:
2108 2108
             /* get low hex digit of checksum */
2109 2109
             if (!isxdigit(ch)) {
2110
-                trace_gdbstub_err_checksum_invalid((uint8_t)ch);
2110
+                trace_gdbstub_err_checksum_invalid(ch);
2111 2111
                 s->state = RS_GETLINE;
2112 2112
                 break;
2113 2113
             }

Loading…
Cancel
Save