Print this page
11506 smatch resync

@@ -33,17 +33,17 @@
         int string;
 };
 
 struct param_info zero_one = {0, 1};
 
-static int handle_format(struct expression *call, char **pp, int *arg_nr)
+static int handle_format(struct expression *call, char **pp, int *arg_nr, bool use_max)
 {
         struct expression *arg;
         char *p = *pp;
         int ret = 1;
         char buf[256];
-        sval_t max;
+        sval_t sval;
 
         p++;  /* we passed it with *p == '%' */
 
         if (*p == '%') {
                 p++;

@@ -139,27 +139,34 @@
                 ret = 1;
                 p++;
                 goto out;
         }
 
-        get_absolute_max(arg, &max);
+        if (use_max) {
+                get_absolute_max(arg, &sval);
+        } else {
+                get_absolute_min(arg, &sval);
+                if (sval_is_negative(sval))
+                        sval.value = 0;
+        }
 
+
         if (*p == 'x' || *p == 'X' || *p == 'p') {
-                ret = snprintf(buf, sizeof(buf), "%llx", max.uvalue);
+                ret = snprintf(buf, sizeof(buf), "%llx", sval.uvalue);
         } else if (*p == 'u') {
-                ret = snprintf(buf, sizeof(buf), "%llu", max.uvalue);
+                ret = snprintf(buf, sizeof(buf), "%llu", sval.uvalue);
         } else if (!expr_unsigned(arg)) {
                 sval_t min;
                 int tmp;
 
-                ret = snprintf(buf, sizeof(buf), "%lld", max.value);
+                ret = snprintf(buf, sizeof(buf), "%lld", sval.value);
                 get_absolute_min(arg, &min);
                 tmp = snprintf(buf, sizeof(buf), "%lld", min.value);
                 if (tmp > ret)
                         ret = tmp;
         } else {
-                ret = snprintf(buf, sizeof(buf), "%lld", max.value);
+                ret = snprintf(buf, sizeof(buf), "%lld", sval.value);
         }
         p++;
 
 out:
         (*arg_nr)++;

@@ -166,11 +173,11 @@
 out_no_arg:
         *pp = p;
         return ret;
 }
 
-int get_formatted_string_size(struct expression *call, int arg)
+int get_formatted_string_size_helper(struct expression *call, int arg, bool use_max)
 {
         struct expression *expr;
         char *p;
         int count;
 

@@ -182,23 +189,32 @@
         count = 0;
         p = expr->string->data;
         while (*p) {
 
                 if (*p == '%') {
-                        count += handle_format(call, &p, &arg);
+                        count += handle_format(call, &p, &arg, use_max);
                 } else if (*p == '\\') {
                         p++;
                 }else {
                         p++;
                         count++;
                 }
         }
 
-        count++; /* count the NUL terminator */
         return count;
 }
 
+int get_formatted_string_size(struct expression *call, int arg)
+{
+        return get_formatted_string_size_helper(call, arg, true);
+}
+
+int get_formatted_string_min_size(struct expression *call, int arg)
+{
+        return get_formatted_string_size_helper(call, arg, false);
+}
+
 static void match_not_limited(const char *fn, struct expression *call, void *info)
 {
         struct param_info *params = info;
         struct range_list *rl;
         struct expression *dest;

@@ -222,14 +238,15 @@
         buf_size = get_array_size_bytes(dest);
         if (buf_size <= 0)
                 return;
 
         size = get_formatted_string_size(call, params->string);
-        if (size <= 0)
+        if (size < 0)
                 return;
         if (size < offset)
                 size -= offset;
+        size++; /* add the NULL terminator */
         if (size <= buf_size)
                 return;
 
         i = 0;
         FOR_EACH_PTR(call->args, arg) {