Avoid deadlock in malloc on backtrace (BZ #16159)
[platform/upstream/linaro-glibc.git] / inet / test-inet6_opt.c
1 #include <netinet/in.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdint.h>
6
7 #define OPT_X   42
8 #define OPT_Y   43
9 #define OPT_Z   44
10
11 static void *
12 encode_inet6_opt (socklen_t *elp)
13 {
14   void *eb = NULL;
15   socklen_t el;
16   int cl;
17   void *db;
18   int offset;
19   uint8_t val1;
20   uint16_t val2;
21   uint32_t val4;
22   uint64_t val8;
23
24   *elp = 0;
25 #define CHECK() \
26   if (cl == -1)                                         \
27     {                                                   \
28       printf ("cl == -1 on line %d\n", __LINE__);       \
29       free (eb);                                        \
30       return NULL;                                      \
31     }
32
33   /* Estimate the length */
34   cl = inet6_opt_init (NULL, 0);
35   CHECK ();
36   cl = inet6_opt_append (NULL, 0, cl, OPT_X, 12, 8, NULL);
37   CHECK ();
38   cl = inet6_opt_append (NULL, 0, cl, OPT_Y, 7, 4, NULL);
39   CHECK ();
40   cl = inet6_opt_append (NULL, 0, cl, OPT_Z, 7, 1, NULL);
41   CHECK ();
42   cl = inet6_opt_finish (NULL, 0, cl);
43   CHECK ();
44   el = cl;
45
46   eb = malloc (el + 8);
47   if (eb == NULL)
48     {
49       puts ("malloc failed");
50       return NULL;
51     }
52   /* Canary.  */
53   memcpy (eb + el, "deadbeef", 8);
54
55   cl = inet6_opt_init (eb, el);
56   CHECK ();
57
58   cl = inet6_opt_append (eb, el, cl, OPT_X, 12, 8, &db);
59   CHECK ();
60   val4 = 0x12345678;
61   offset = inet6_opt_set_val (db, 0, &val4, sizeof  (val4));
62   val8 = 0x0102030405060708LL;
63   inet6_opt_set_val (db, offset, &val8, sizeof  (val8));
64
65   cl = inet6_opt_append (eb, el, cl, OPT_Y, 7, 4, &db);
66   CHECK ();
67   val1 = 0x01;
68   offset = inet6_opt_set_val (db, 0, &val1, sizeof  (val1));
69   val2 = 0x1331;
70   offset = inet6_opt_set_val (db, offset, &val2, sizeof  (val2));
71   val4 = 0x01020304;
72   inet6_opt_set_val (db, offset, &val4, sizeof  (val4));
73
74   cl = inet6_opt_append (eb, el, cl, OPT_Z, 7, 1, &db);
75   CHECK ();
76   inet6_opt_set_val (db, 0, (void *) "abcdefg", 7);
77
78   cl = inet6_opt_finish (eb, el, cl);
79   CHECK ();
80
81   if (memcmp (eb + el, "deadbeef", 8) != 0)
82     {
83       puts ("Canary corrupted");
84       free (eb);
85       return NULL;
86     }
87   *elp = el;
88   return eb;
89 }
90
91 int
92 decode_inet6_opt (void *eb, socklen_t el)
93 {
94   int ret = 0;
95   int seq = 0;
96   int cl = 0;
97   int offset;
98   uint8_t type;
99   socklen_t len;
100   uint8_t val1;
101   uint16_t val2;
102   uint32_t val4;
103   uint64_t val8;
104   void *db;
105   char buf[8];
106
107   while ((cl = inet6_opt_next (eb, el, cl, &type, &len, &db)) != -1)
108     switch (type)
109       {
110       case OPT_X:
111         if (seq++ != 0)
112           {
113             puts ("OPT_X is not first");
114             ret = 1;
115           }
116         if (len != 12)
117           {
118             printf ("OPT_X's length %d != 12\n", len);
119             ret = 1;
120           }
121         offset = inet6_opt_get_val (db, 0, &val4, sizeof (val4));
122         if (val4 != 0x12345678)
123           {
124             printf ("OPT_X's val4 %x != 0x12345678\n", val4);
125             ret = 1;
126           }
127         offset = inet6_opt_get_val (db, offset, &val8, sizeof (val8));
128         if (offset != len || val8 != 0x0102030405060708LL)
129           {
130             printf ("OPT_X's val8 %llx != 0x0102030405060708\n",
131                     (long long) val8);
132             ret = 1;
133           }
134         break;
135       case OPT_Y:
136         if (seq++ != 1)
137           {
138             puts ("OPT_Y is not second");
139             ret = 1;
140           }
141         if (len != 7)
142           {
143             printf ("OPT_Y's length %d != 7\n", len);
144             ret = 1;
145           }
146         offset = inet6_opt_get_val (db, 0, &val1, sizeof (val1));
147         if (val1 != 0x01)
148           {
149             printf ("OPT_Y's val1 %x != 0x01\n", val1);
150             ret = 1;
151           }
152         offset = inet6_opt_get_val (db, offset, &val2, sizeof (val2));
153         if (val2 != 0x1331)
154           {
155             printf ("OPT_Y's val2 %x != 0x1331\n", val2);
156             ret = 1;
157           }
158         offset = inet6_opt_get_val (db, offset, &val4, sizeof (val4));
159         if (offset != len || val4 != 0x01020304)
160           {
161             printf ("OPT_Y's val4 %x != 0x01020304\n", val4);
162             ret = 1;
163           }
164         break;
165       case OPT_Z:
166         if (seq++ != 2)
167           {
168             puts ("OPT_Z is not third");
169             ret = 1;
170           }
171         if (len != 7)
172           {
173             printf ("OPT_Z's length %d != 7\n", len);
174             ret = 1;
175           }
176         offset = inet6_opt_get_val (db, 0, buf, 7);
177         if (offset != len || memcmp (buf, "abcdefg", 7) != 0)
178           {
179             buf[7] = '\0';
180             printf ("OPT_Z's buf \"%s\" != \"abcdefg\"\n", buf);
181             ret = 1;
182           }
183         break;
184       default:
185         printf ("Unknown option %d\n", type);
186         ret = 1;
187         break;
188       }
189   if (seq != 3)
190     {
191       puts ("Didn't see all of OPT_X, OPT_Y and OPT_Z");
192       ret = 1;
193     }
194   return ret;
195 }
196
197 int
198 main (void)
199 {
200   void *eb;
201   socklen_t el;
202   eb = encode_inet6_opt (&el);
203   if (eb == NULL)
204     return 1;
205   if (decode_inet6_opt (eb, el))
206     return 1;
207   return 0;
208 }