blob: make blob_parse_untrusted more permissive
[project/libubox.git] / tests / test-blobmsg_check_array.c
1 #include <stdio.h>
2
3 #include "blobmsg.h"
4
5 /*
6 * This test tests a blob of this form...
7 *
8 {
9 "array_a" : [
10 {
11 "array_b": [
12 "1"
13 ]
14 }
15 ]
16 }
17 *
18 */
19
20
21 enum {
22 ARRAY_A = 0,
23 ARRAY_B = 0,
24 };
25
26 static char const array_a[] = "array_a";
27 static char const array_b[] = "array_b";
28
29 static const struct blobmsg_policy pol_a[] = {
30 [ARRAY_A] = {
31 .name = array_a,
32 .type = BLOBMSG_TYPE_ARRAY
33 }
34 };
35
36 static const struct blobmsg_policy pol_b[] = {
37 [ARRAY_B] = {
38 .name = array_b,
39 .type = BLOBMSG_TYPE_ARRAY
40 }
41 };
42
43 #ifndef ARRAY_SIZE
44 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
45 #endif
46
47 static int
48 check_table_a_entries(struct blob_attr *attr)
49 {
50 struct blob_attr *cur;
51 size_t rem;
52 int entry_number = 0;
53
54 blobmsg_for_each_attr(cur, attr, rem) {
55 int failed = 0;
56
57 fprintf(stderr, "Process %s: entry %d\n", array_a, entry_number);
58
59 struct blob_attr *tb[ARRAY_SIZE(pol_b)];
60
61 if (blobmsg_parse(pol_b, ARRAY_SIZE(pol_b), tb,
62 blobmsg_data(cur), blobmsg_data_len(cur)) != 0) {
63 fprintf(stderr, "Policy %s parse failed\n", array_b);
64 return -1;
65 }
66
67 if (tb[ARRAY_B] == NULL) {
68 fprintf(stderr, "%s not found\n", array_b);
69 return -1;
70 }
71
72 /*
73 * This is the test that fails when blobmsg_check_array() passes the
74 * length obtained by blob_len(attr).
75 * It succeeds when blobmsg_check_array() uses blob_len(attr), which is
76 * equivalent to the origianl code, pre the length check changes.
77 */
78 if (blobmsg_check_array(tb[ARRAY_B], BLOBMSG_TYPE_STRING) < 0) {
79 fprintf(stderr, "Failed blobmsg_check_array() (STRING) on %s\n",
80 array_b);
81 failed = 1;
82 }
83
84 /*
85 * Continue outputting the strings even though the test above might
86 * have failed.
87 * This will show that the array does actually contain the expected
88 * string.
89 */
90
91 struct blob_attr *cur2;
92 size_t rem2;
93
94 blobmsg_for_each_attr(cur2, tb[ARRAY_B], rem2) {
95 fprintf(stderr, "%s contains string: %s\n",
96 array_b, blobmsg_get_string(cur2));
97 }
98
99
100 entry_number++;
101
102 if (failed)
103 return -1;
104 }
105
106 return 0;
107 }
108
109 static int
110 check_message(struct blob_buf *buf)
111 {
112 struct blob_attr *tb[ARRAY_SIZE(pol_a)];
113
114 if (blobmsg_parse(pol_a, ARRAY_SIZE(pol_a), tb,
115 blob_data(buf->head), blobmsg_data_len(buf->head)) != 0) {
116 fprintf(stderr, "Policy %s parse failed\n", array_a);
117 return -1;
118 }
119
120 if (tb[ARRAY_A] == NULL) {
121 fprintf(stderr, "%s not found\n", array_a);
122 return -1;
123 }
124
125 int const result = blobmsg_check_array(tb[ARRAY_A], BLOBMSG_TYPE_TABLE);
126
127 if (result < 0) {
128 fprintf(stderr, "Failed blobmsg_check_array() (TABLE) on %s (%d)\n",
129 array_a, result);
130 return -1;
131 }
132
133 return check_table_a_entries(tb[ARRAY_A]);
134 }
135
136 static void
137 fill_message(struct blob_buf * const buf)
138 {
139 void * const tbl_a = blobmsg_open_array(buf, "array_a");
140 void * const obj = blobmsg_open_table(buf, NULL);
141
142 void * const tbl_b = blobmsg_open_array(buf, "array_b");
143
144 blobmsg_add_string(buf, NULL, "1");
145
146 blobmsg_close_array(buf, tbl_b);
147
148 blobmsg_close_table(buf, obj);
149
150 blobmsg_close_array(buf, tbl_a);
151 }
152
153 int main(int argc, char **argv)
154 {
155 int result;
156 static struct blob_buf buf;
157
158 blobmsg_buf_init(&buf);
159 fill_message(&buf);
160
161 result = check_message(&buf);
162 if (result == 0)
163 fprintf(stderr, "blobmsg_check_array() test passed\n");
164
165 if (buf.buf != NULL)
166 free(buf.buf);
167
168 return result ? EXIT_FAILURE : EXIT_SUCCESS;
169 }