Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix crash when pretty printing arrays of arrays

  • Loading branch information...
commit 460aeed9420deef9fae9b18e3f67588c5e0dcec9 1 parent a16dd20
Nick Gasson authored
74 src/rt/pprint.c
View
@@ -22,9 +22,15 @@
#include <inttypes.h>
#include <stdio.h>
#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
static bool pp_char_enum(type_t type)
{
+ if (type_kind(type) != T_ENUM)
+ return false;
+
bool all_char = true;
unsigned nlit = type_enum_literals(type);
for (unsigned i = 0; i < nlit; i++) {
@@ -34,60 +40,70 @@ static bool pp_char_enum(type_t type)
return all_char;
}
-static size_t pp_one(char *p, size_t len, type_t type, uint64_t value)
+static void pp_one(type_t type, uint64_t value)
{
switch (type_kind(type)) {
case T_INTEGER:
- return snprintf(p, len, "%"PRIu64, value);
+ static_printf("%"PRIu64, value);
+ break;
case T_ENUM:
{
assert(value < type_enum_literals(type));
const char *s = istr(tree_ident(type_enum_literal(type, value)));
if (*s == '\'')
- return snprintf(p, len, "%c", *(s + 1));
+ static_printf("%c", *(s + 1));
else
- return snprintf(p, len, "%s", s);
+ static_printf("%s", s);
}
+ break;
default:
- return snprintf(p, len, "%"PRIx64, value);
+ static_printf("%"PRIx64, value);
}
}
-const char *pprint(tree_t t, uint64_t *values, unsigned len)
+static const uint64_t *pp_array(type_t type, const uint64_t *values)
{
- static char buf[1024];
+ type_t elem = type_base_recur(type_elem(type));
+ bool all_char = pp_char_enum(elem);
- char *p = buf;
- const char *end = buf + sizeof(buf);
+ static_printf(all_char ? "\"" : "(");
- type_t type = tree_type(t);
+ range_t r = type_dim(type, 0);
+ const int left = assume_int(r.left);
+ const int right = assume_int(r.right);
+ const int step = (r.kind == RANGE_TO) ? 1 : -1;
- if (type_is_array(type)) {
- type_t elem = type_base_recur(type_elem(type));
- bool all_char = pp_char_enum(elem);
+ for (int i = left; i != right + step; i += step) {
+ if (!all_char && (i != left))
+ static_printf(",");
+ if (type_is_array(elem))
+ values = pp_array(elem, values);
+ else
+ pp_one(elem, *values++);
+ }
- p += snprintf(p, end - p, all_char ? "\"" : "(");
+ static_printf(all_char ? "\"" : ")");
- unsigned left = 0, right = len - 1;
- int step = 1;
- if (type_dim(type, 0).kind == RANGE_DOWNTO) {
- left = len - 1;
- right = 0;
- step = -1;
- }
+ return values;
+}
- for (unsigned i = left; i != right + step; i += step) {
- if (!all_char && (i != left))
- p += snprintf(p, end - p, ",");
- p += pp_one(p, end - p, elem, values[i]);
- }
+const char *pprint(tree_t t, const uint64_t *values, size_t len)
+{
+ static char buf[1024];
- p += snprintf(p, end - p, all_char ? "\"" : ")");
- }
+ static_printf_begin(buf, sizeof(buf));
+
+ type_t type = tree_type(t);
+
+ if (type_is_array(type))
+ pp_array(type, values);
else
- pp_one(p, end - p, type_base_recur(type), values[0]);
+ pp_one(type_base_recur(type), values[0]);
+
+ for (int i = 0; i < 3; i++)
+ *(buf + sizeof(buf) - 2 - i) = '.';
return buf;
}
2  src/rt/rt.h
View
@@ -41,7 +41,7 @@ void jit_bind_fn(const char *name, void *ptr);
void shell_run(struct tree *e);
-const char *pprint(struct tree *t, uint64_t *values, unsigned len);
+const char *pprint(struct tree *t, const uint64_t *values, size_t len);
void vcd_init(const char *file, struct tree *top);
void vcd_restart(void);
11 src/rt/rtkern.c
View
@@ -1200,12 +1200,15 @@ static void rt_slave_read_signal(slave_read_signal_msg_t *msg)
assert(tree_kind(t) == T_SIGNAL_DECL);
type_t type = tree_type(t);
-
- int64_t low = 0, high = 0;
- if (type_kind(type) == T_CARRAY)
+ size_t len = 1;
+ while (type_is_array(type)) {
+ int64_t low = 0, high = 0;
range_bounds(type_dim(type, 0), &low, &high);
+ len *= (high - low + 1);
- assert(msg->len <= high - low + 1);
+ type = type_elem(type);
+ }
+ assert(len <= msg->len);
struct signal *sig = tree_attr_ptr(t, i_signal);
14 src/rt/shell.c
View
@@ -116,13 +116,19 @@ static int shell_cmd_show(ClientData cd, Tcl_Interp *interp,
if (tree_kind(d) != T_SIGNAL_DECL)
continue;
- int64_t low = 0, high = 0;
- if (type_kind(tree_type(d)) == T_CARRAY)
- range_bounds(type_dim(tree_type(d), 0), &low, &high);
+ size_t len = 1;
+ type_t type = tree_type(d);
+ while (type_is_array(type)) {
+ int64_t low = 0, high = 0;
+ range_bounds(type_dim(type, 0), &low, &high);
+ len *= (high - low + 1);
+
+ type = type_elem(type);
+ }
slave_read_signal_msg_t msg = {
.index = tree_index(d),
- .len = high - low + 1
+ .len = len
};
slave_post_msg(SLAVE_READ_SIGNAL, &msg, sizeof(msg));
35 src/util.c
View
@@ -38,6 +38,7 @@
#include <stdint.h>
#include <unistd.h>
#include <ctype.h>
+#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -113,9 +114,11 @@ struct option {
int value;
};
-static error_fn_t error_fn = def_error_fn;
-static bool want_color = false;
+static error_fn_t error_fn = def_error_fn;
+static bool want_color = false;
static struct option *options = NULL;
+static char *printf_buf = NULL;
+static size_t printf_remain = 0;
static void paginate_msg(const char *fmt, va_list ap, int left, int right)
{
@@ -721,3 +724,31 @@ char *get_fmt_buf(size_t len)
return *bufp;
}
+
+void static_printf_begin(char *buf, size_t len)
+{
+ printf_buf = buf;
+ printf_remain = len - 1;
+ buf[len - 1] = '\0';
+}
+
+void static_printf(const char *fmt, ...)
+{
+ assert(printf_buf != NULL);
+
+ if (printf_remain == 0)
+ return;
+
+ va_list ap;
+ va_start(ap, fmt);
+
+ int n = vsnprintf(printf_buf, printf_remain, fmt, ap);
+ if ((n < 0) || (n > printf_remain))
+ printf_remain = 0;
+ else {
+ printf_remain -= n;
+ printf_buf += n;
+ }
+
+ va_end(ap);
+}
7 src/util.h
View
@@ -32,6 +32,9 @@
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
void *xmalloc(size_t size);
void *xrealloc(void *ptr, size_t size);
@@ -90,4 +93,8 @@ int opt_get_int(const char *name);
char *get_fmt_buf(size_t len);
+void static_printf_begin(char *buf, size_t len);
+void static_printf(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
+
#endif // _UTIL_H
Please sign in to comment.
Something went wrong with that request. Please try again.