Add proper error checking in asciihex2int functions
authorHugo Villeneuve <hugo@hugovil.com>
Sun, 16 Feb 2014 06:51:47 +0000 (01:51 -0500)
committerHugo Villeneuve <hugo@hugovil.com>
Sun, 16 Feb 2014 06:51:47 +0000 (01:51 -0500)
src/cli/scanner.l
src/common/hexfile.c
src/common/hexfile.h
src/gtk/memwin.c
src/gtk/pgmwin.c
src/gtk/pswwin.c
src/gtk/regwin.c

index 1ef440d..919d71e 100644 (file)
@@ -17,9 +17,26 @@ hextail              ({digit}|{alpha}){1,8}
 hex1           0[xX]{hextail}
 hex2           ${hextail}
 
+
 %%
-{hex1}      { yylval.number = asciihex2int(yytext); return NUMBER; }
-{hex2}      { yylval.number = asciihex2int(&yytext[1]); return NUMBER; }
+{hex1}      {
+                /*
+                 * No need to check return value of asciihex2int, because lex
+                 * always passes a valid ASCII hex string.
+                 */
+                yylval.number = asciihex2int(&yytext[2]); /* Skip "0x" prefix */
+                return NUMBER;
+            }
+{hex2}      {
+                /*
+                 * No need to check return value of asciihex2int, because lex
+                 * always passes a valid ASCII hex string.
+                 */
+                yylval.number = asciihex2int(&yytext[1]); /* Skip "$" prefix */
+                return NUMBER;
+            }
+
+
 [0-9]+      { yylval.number = atoi(yytext); return NUMBER; }
 [h?]        return TOK_HELP;
 sb          return TOK_SB;
index ee0c745..b9aff06 100644 (file)
 
 static int asciihex2int_error;
 
+int
+asciihex2int_get_error(void)
+{
+       return asciihex2int_error;
+}
+
 /* Convert integer to ASCII hex string. */
 void
 int2asciihex(int val, char *str, int width)
@@ -43,35 +49,24 @@ int2asciihex(int val, char *str, int width)
                sprintf(str , "Err");
 }
 
-/* Convert ASCII hex string to integer. */
-int
-asciihex2int(char *str)
-{
-       int val;
-       int rc;
-
-       rc = sscanf(str, "%X", &val);
-
-       if (rc == 0) {
-               log_err("ASCII to hex conversion failure");
-               asciihex2int_error = true;
-       }
-
-       return val;
-}
-
-/* Convert an ascii string to an hexadecimal number. */
+/*
+ * Convert ASCII string in hexadecimal notation to integer, up to length
+ * characters.
+ * The string contains only [0-9] and [a-f] characters (no "0x" prefix).
+ */
 static unsigned int
-asciihex2int_len(char *istring, int length)
+asciihex2int_len(char *str, int length)
 {
        unsigned int result = 0;
        int i, ascii_code;
 
-       if (!length || (length > (int) strlen(istring)))
-               length = strlen(istring);
+       asciihex2int_error = false;
+
+       if (!length || (length > (int) strlen(str)))
+               length = strlen(str);
 
        for (i = 0; i < length; i++) {
-               ascii_code = istring[i];
+               ascii_code = str[i];
                if (ascii_code > 0x39)
                        ascii_code &= 0xDF;
 
@@ -86,11 +81,23 @@ asciihex2int_len(char *istring, int length)
                } else {
                        log_err("ASCII to hex conversion failure");
                        asciihex2int_error = true;
+                       return 0;
                }
        }
        return result;
 }
 
+/*
+ * Convert ASCII string in hexadecimal notation to integer, up to \0 end character.
+ * The string must not contain prefix "0x", only [0-9] and [a-f] characters.
+ */
+unsigned int
+asciihex2int(char *str)
+{
+       /* Set length to zero to use full length of string. */
+       return asciihex2int_len(str, 0);
+}
+
 /*
  * Return value:
  *   true:  success
index f9a258b..d130e1c 100644 (file)
 #ifndef HEXFILE_H
 #define HEXFILE_H 1
 
+int
+asciihex2int_get_error(void);
+
 void
 int2asciihex(int val, char *str, int width);
 
-int
+unsigned int
 asciihex2int(char *str);
 
 int
index 2ea618a..96be0b5 100644 (file)
@@ -104,6 +104,8 @@ memwin_cell_edited(GtkCellRendererText *cell, gchar *path_string,
 
        /* Get base address. */
        gtk_tree_model_get(model, &iter, COL_ADDRESS, &str, -1);
+
+       /* No need to check error, has already been validated. */
        address = asciihex2int(str);
 
        /* Convert column number (1, 2, 3...) to index (0, 1, 2...) */
@@ -115,9 +117,12 @@ memwin_cell_edited(GtkCellRendererText *cell, gchar *path_string,
 
        /* Convert new value (asciihex) to integer. */
        new = asciihex2int(new_str);
-       if ((new < 0) || (new > 255)) {
-               log_info("  new value: out of range");
-               new = old; /* Put back old value... */
+       if (asciihex2int_get_error()) {
+               log_warn("  new value: invalid");
+               return;
+       } else if ((new < 0) || (new > 255)) {
+               log_warn("  new value: out of range");
+               return;
        } else {
                log_info("  new value: $%02X", new);
        }
index 4c35d7f..d1ad010 100644 (file)
@@ -134,6 +134,7 @@ pgmwin_sel_changed_event(GtkWidget *widget, GdkEvent *event, gpointer data)
                gtk_tree_model_get(model, &iter, COL_ADDR, &str_addr, -1);
 
                /* Convert hex address in ASCII to integer. */
+               /* No need to check error, has already been validated. */
                val = asciihex2int(str_addr);
 
                log_debug("  row address is: $%04X", val);
index e678abf..f0badda 100644 (file)
@@ -110,9 +110,12 @@ pswwin_cell_edited(GtkCellRendererText *cell, gchar *path_string,
        /* Convert new value (asciihex) to integer. */
        new = asciihex2int(new_str);
 
-       if ((new != 0) && (new != 1)) {
-               log_info("  new value: out of range");
-               new = old; /* Put back old value... */
+       if (asciihex2int_get_error()) {
+               log_warn("  new value: invalid");
+               return;
+       } else if ((new != 0) && (new != 1)) {
+               log_warn("  new value: out of range");
+               return;
        } else {
                log_info("  new value: %d", new);
        }
index 2358685..d3fcb8d 100644 (file)
@@ -88,10 +88,16 @@ regwin_cell_edited(GtkCellRendererText *cell, gchar *path_string,
        /* Read current (old) value. */
        gtk_tree_model_get(model, &iter, COL_VAL, &str, -1);
 
+       /* No need to check error, has already been validated. */
        old = asciihex2int(str);
        log_info("  old value: $%04X", old);
 
        new = asciihex2int(new_str);
+       if (asciihex2int_get_error()) {
+               log_warn("  new value: invalid");
+               return;
+       }
+
        log_info("  new value: $%04X", new);
 
        /* Store new value in emulator register (if in range). */