ofp-parse: Fix parsing of register values 2**31 and greater.
authorBen Pfaff <blp@nicira.com>
Fri, 12 Aug 2011 21:59:11 +0000 (14:59 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 12 Aug 2011 21:59:11 +0000 (14:59 -0700)
Reported-by: Ethan Jackson <ethan@nicira.com>
lib/ofp-parse.c

index e6a6af120c5ae68803090797df830e1986051e2a..5c7feb2e76b8812d1b22c0f65b19196d6361874e 100644 (file)
@@ -812,14 +812,20 @@ parse_field_value(struct cls_rule *rule, enum field_index index,
 static void
 parse_reg_value(struct cls_rule *rule, int reg_idx, const char *value)
 {
-    uint32_t reg_value, reg_mask;
+    /* This uses an oversized destination field (64 bits when 32 bits would do)
+     * because some sscanf() implementations truncate the range of %i
+     * directives, so that e.g. "%"SCNi16 interprets input of "0xfedc" as a
+     * value of 0x7fff.  The other alternatives are to allow only a single
+     * radix (e.g. decimal or hexadecimal) or to write more sophisticated
+     * parsers. */
+    unsigned long long int reg_value, reg_mask;
 
     if (!strcmp(value, "ANY") || !strcmp(value, "*")) {
         cls_rule_set_reg_masked(rule, reg_idx, 0, 0);
-    } else if (sscanf(value, "%"SCNi32"/%"SCNi32,
+    } else if (sscanf(value, "%lli/%lli",
                       &reg_value, &reg_mask) == 2) {
         cls_rule_set_reg_masked(rule, reg_idx, reg_value, reg_mask);
-    } else if (sscanf(value, "%"SCNi32, &reg_value)) {
+    } else if (sscanf(value, "%lli", &reg_value)) {
         cls_rule_set_reg(rule, reg_idx, reg_value);
     } else {
         ovs_fatal(0, "register fields must take the form <value> "