Fix possible buffer overrun
[pspp] / src / output / charts / barchart.c
index 07a39e818f65193b6ddc6ed4816eab19c3a65dd5..aca03ee8c41ad3320f11d499ddfd6fe52baf619a 100644 (file)
@@ -85,7 +85,7 @@ compare_freq_2level_ptr_3way (const void *a_, const void *b_, const void *bc_)
 */
 struct chart_item *
 barchart_create (const struct variable **var, int n_vars,
-                const char *ylabel, 
+                const char *ylabel, bool percent, 
                 struct freq *const *cats, int n_cats)
 {
   struct barchart *bar;
@@ -100,6 +100,7 @@ barchart_create (const struct variable **var, int n_vars,
   assert (n_vars >= 1);
 
   bar = xzalloc (sizeof *bar);
+  bar->percent = percent;
   bar->var = var;
   bar->n_vars = n_vars;
   bar->n_nzcats = n_cats;
@@ -136,8 +137,9 @@ barchart_create (const struct variable **var, int n_vars,
            {
              struct category *s = xzalloc (sizeof *s);
              s->idx = idx++;
-             value_init (&s->val, var_get_width (var[pidx]));
-             value_copy (&s->val, &src->values[pidx], var_get_width (var[pidx]));
+             s->width = var_get_width (var[pidx]);
+             value_init (&s->val, s->width);
+             value_copy (&s->val, &src->values[pidx], s->width);
              ds_init_empty (&s->label);
              var_append_value_name (var[pidx], &s->val, &s->label);
 
@@ -173,7 +175,8 @@ barchart_create (const struct variable **var, int n_vars,
            {
              struct category *s = xzalloc (sizeof *s);
              s->idx = idx++;
-             value_init (&s->val, var_get_width (var[sidx]));
+             s->width = var_get_width (var[sidx]);
+             value_init (&s->val, s->width);
              value_copy (&s->val, &src->values[sidx], var_get_width (var[sidx]));
              ds_init_empty (&s->label);
              var_append_value_name (var[sidx], &s->val, &s->label);
@@ -211,18 +214,19 @@ barchart_create (const struct variable **var, int n_vars,
        struct freq *c = cats[i];
 
        struct freq *foo;
-       int flag = 0;
+       bool flag = false;
        size_t hash = hash_freq_2level_ptr (&c, bar);
        HMAP_FOR_EACH_WITH_HASH (foo, struct freq, node, hash, &level2table)
          {
            if (0 == compare_freq_2level_ptr_3way (&foo, &c, bar))
              {
                foo->count += c->count;
+               bar->total_count += c->count;
                
                if (foo->count > bar->largest)
                  bar->largest = foo->count;
                
-               flag = 1;
+               flag = true;
                break;
              }
          }
@@ -235,6 +239,7 @@ barchart_create (const struct variable **var, int n_vars,
            if (c->count > bar->largest)
              bar->largest = aggregated_freq->count;
            
+           bar->total_count += c->count;
            bar->cats[x++] = aggregated_freq;
          }
       }
@@ -256,6 +261,8 @@ destroy_cat_map (struct hmap *m)
   struct category *next = NULL;
   HMAP_FOR_EACH_SAFE (foo, next, struct category, node, m)
     {
+      value_destroy (&foo->val, foo->width);
+
       ds_destroy (&foo->label);
       free (foo);
     }