aboutsummaryrefslogtreecommitdiff
path: root/lib/ofp-parse.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2011-08-12 14:59:11 -0700
committerBen Pfaff <blp@nicira.com>2011-08-12 14:59:11 -0700
commit72f7976600581cc9c57915dad150f7984c33e18b (patch)
tree58bda21bbfbd9780351984f7ad05857ea5b14913 /lib/ofp-parse.c
parent0f2bbc23998430276a2f530ede1de40e45098441 (diff)
ofp-parse: Fix parsing of register values 2**31 and greater.
Reported-by: Ethan Jackson <ethan@nicira.com>
Diffstat (limited to 'lib/ofp-parse.c')
-rw-r--r--lib/ofp-parse.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index e6a6af12..5c7feb2e 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -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> "