blob: make blob_parse_untrusted more permissive
[project/libubox.git] / tests / test-blobmsg.c
1 #include <stdio.h>
2 #include <float.h>
3 #include <limits.h>
4 #include <stdint.h>
5 #include <inttypes.h>
6
7 #include "blobmsg.h"
8 #include "blobmsg_json.h"
9
10 static const char *indent_str = "\t\t\t\t\t\t\t\t\t\t\t\t\t";
11
12 #define indent_printf(indent, ...) do { \
13 if (indent > 0) \
14 fwrite(indent_str, indent, 1, stderr); \
15 fprintf(stderr, __VA_ARGS__); \
16 } while(0)
17
18 static void dump_attr_data(struct blob_attr *data, int indent, int next_indent);
19
20 static void
21 dump_table(struct blob_attr *head, size_t len, int indent, bool array)
22 {
23 struct blob_attr *attr;
24 struct blobmsg_hdr *hdr;
25
26 indent_printf(indent, "{\n");
27 __blob_for_each_attr(attr, head, len) {
28 hdr = blob_data(attr);
29 if (!array)
30 indent_printf(indent + 1, "%s : ", hdr->name);
31 dump_attr_data(attr, 0, indent + 1);
32 }
33 indent_printf(indent, "}\n");
34 }
35
36 static void dump_attr_data(struct blob_attr *data, int indent, int next_indent)
37 {
38 int type = blobmsg_type(data);
39 switch(type) {
40 case BLOBMSG_TYPE_STRING:
41 indent_printf(indent, "%s (str)\n", blobmsg_get_string(data));
42 break;
43 case BLOBMSG_TYPE_INT8:
44 indent_printf(indent, "%d (i8)\n", (int8_t) blobmsg_get_u8(data));
45 break;
46 case BLOBMSG_TYPE_INT16:
47 indent_printf(indent, "%d (i16)\n", (int16_t) blobmsg_get_u16(data));
48 break;
49 case BLOBMSG_TYPE_INT32:
50 indent_printf(indent, "%d (i32)\n", (int32_t) blobmsg_get_u32(data));
51 break;
52 case BLOBMSG_TYPE_INT64:
53 indent_printf(indent, "%"PRId64" (i64)\n", (int64_t) blobmsg_get_u64(data));
54 break;
55 case BLOBMSG_TYPE_DOUBLE:
56 indent_printf(indent, "%lf (dbl)\n", blobmsg_get_double(data));
57 break;
58 case BLOBMSG_TYPE_TABLE:
59 case BLOBMSG_TYPE_ARRAY:
60 if (!indent)
61 indent_printf(indent, "\n");
62 dump_table(blobmsg_data(data), blobmsg_data_len(data),
63 next_indent, type == BLOBMSG_TYPE_ARRAY);
64 break;
65 }
66 }
67
68 enum {
69 FOO_MESSAGE,
70 FOO_LIST,
71 FOO_TESTDATA
72 };
73
74 static const struct blobmsg_policy pol[] = {
75 [FOO_MESSAGE] = {
76 .name = "message",
77 .type = BLOBMSG_TYPE_STRING,
78 },
79 [FOO_LIST] = {
80 .name = "list",
81 .type = BLOBMSG_TYPE_ARRAY,
82 },
83 [FOO_TESTDATA] = {
84 .name = "testdata",
85 .type = BLOBMSG_TYPE_TABLE,
86 },
87 };
88
89 #ifndef ARRAY_SIZE
90 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
91 #endif
92
93 static void dump_message(struct blob_buf *buf)
94 {
95 struct blob_attr *tb[ARRAY_SIZE(pol)];
96
97 if (blobmsg_parse(pol, ARRAY_SIZE(pol), tb, blob_data(buf->head), blob_len(buf->head)) != 0) {
98 fprintf(stderr, "Parse failed\n");
99 return;
100 }
101 if (tb[FOO_MESSAGE])
102 fprintf(stderr, "Message: %s\n", (char *) blobmsg_data(tb[FOO_MESSAGE]));
103
104 if (tb[FOO_LIST]) {
105 fprintf(stderr, "List: ");
106 dump_table(blobmsg_data(tb[FOO_LIST]), blobmsg_data_len(tb[FOO_LIST]), 0, true);
107 }
108 if (tb[FOO_TESTDATA]) {
109 fprintf(stderr, "Testdata: ");
110 dump_table(blobmsg_data(tb[FOO_TESTDATA]), blobmsg_data_len(tb[FOO_TESTDATA]), 0, false);
111 }
112 }
113
114 static void
115 fill_message(struct blob_buf *buf)
116 {
117 void *tbl;
118
119 blobmsg_add_string(buf, "message", "Hello, world!");
120
121 tbl = blobmsg_open_table(buf, "testdata");
122 blobmsg_add_double(buf, "dbl-min", DBL_MIN);
123 blobmsg_add_double(buf, "dbl-max", DBL_MAX);
124 blobmsg_add_u8(buf, "foo", 0);
125 blobmsg_add_u8(buf, "poo", 100);
126 blobmsg_add_u8(buf, "moo-min", INT8_MIN);
127 blobmsg_add_u8(buf, "moo-max", INT8_MAX);
128 blobmsg_add_u16(buf, "bar-min", INT16_MIN);
129 blobmsg_add_u16(buf, "bar-max", INT16_MAX);
130 blobmsg_add_u32(buf, "baz-min", INT32_MIN);
131 blobmsg_add_u32(buf, "baz-max", INT32_MAX);
132 blobmsg_add_u64(buf, "taz-min", INT64_MIN);
133 blobmsg_add_u64(buf, "taz-max", INT64_MAX);
134 blobmsg_add_string(buf, "world", "2");
135 blobmsg_close_table(buf, tbl);
136
137 tbl = blobmsg_open_array(buf, "list");
138 blobmsg_add_u8(buf, NULL, 0);
139 blobmsg_add_u8(buf, NULL, 100);
140 blobmsg_add_u8(buf, NULL, INT8_MIN);
141 blobmsg_add_u8(buf, NULL, INT8_MAX);
142 blobmsg_add_u16(buf, NULL, INT16_MIN);
143 blobmsg_add_u16(buf, NULL, INT16_MAX);
144 blobmsg_add_u32(buf, NULL, INT32_MIN);
145 blobmsg_add_u32(buf, NULL, INT32_MAX);
146 blobmsg_add_u64(buf, NULL, INT64_MIN);
147 blobmsg_add_u64(buf, NULL, INT64_MAX);
148 blobmsg_add_double(buf, NULL, DBL_MIN);
149 blobmsg_add_double(buf, NULL, DBL_MAX);
150 blobmsg_close_table(buf, tbl);
151 }
152
153 int main(int argc, char **argv)
154 {
155 char *json = NULL;
156 static struct blob_buf buf;
157
158 blobmsg_buf_init(&buf);
159 fill_message(&buf);
160 fprintf(stderr, "[*] blobmsg dump:\n");
161 dump_message(&buf);
162
163 json = blobmsg_format_json(buf.head, true);
164 if (!json)
165 exit(EXIT_FAILURE);
166
167 fprintf(stderr, "\n[*] blobmsg to json: %s\n", json);
168
169 blobmsg_buf_init(&buf);
170 if (!blobmsg_add_json_from_string(&buf, json))
171 exit(EXIT_FAILURE);
172
173 fprintf(stderr, "\n[*] blobmsg from json:\n");
174 dump_message(&buf);
175
176 if (buf.buf)
177 free(buf.buf);
178 free(json);
179
180 return 0;
181 }