2889d17b5556a2d913f5876966bbf694057f30fa
[ric-app/kpimon.git] / asn1c_defs / all-defs / OBJECT_IDENTIFIER.c
1 /*-\r
2  * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.\r
3  * Redistribution and modifications are permitted subject to BSD license.\r
4  */\r
5 #include <asn_internal.h>\r
6 #include <INTEGER.h>\r
7 #include <OBJECT_IDENTIFIER.h>\r
8 #include <OCTET_STRING.h>\r
9 #include <limits.h>     /* for CHAR_BIT */\r
10 #include <errno.h>\r
11 \r
12 /*\r
13  * OBJECT IDENTIFIER basic type description.\r
14  */\r
15 static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = {\r
16         (ASN_TAG_CLASS_UNIVERSAL | (6 << 2))\r
17 };\r
18 asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER = {\r
19         ASN__PRIMITIVE_TYPE_free,\r
20         OBJECT_IDENTIFIER_print,\r
21         OCTET_STRING_compare,   /* Implemented in terms of a string comparison */\r
22         ber_decode_primitive,\r
23         der_encode_primitive,\r
24         OBJECT_IDENTIFIER_decode_xer,\r
25         OBJECT_IDENTIFIER_encode_xer,\r
26 #ifdef  ASN_DISABLE_OER_SUPPORT\r
27         0,\r
28         0,\r
29 #else\r
30         OBJECT_IDENTIFIER_decode_oer,\r
31         OBJECT_IDENTIFIER_encode_oer,\r
32 #endif  /* ASN_DISABLE_OER_SUPPORT */\r
33 #ifdef  ASN_DISABLE_PER_SUPPORT\r
34         0,\r
35         0,\r
36         0,\r
37         0,\r
38 #else\r
39         OCTET_STRING_decode_uper,\r
40         OCTET_STRING_encode_uper,\r
41         OCTET_STRING_decode_aper,\r
42         OCTET_STRING_encode_aper,\r
43 #endif  /* ASN_DISABLE_PER_SUPPORT */\r
44         OBJECT_IDENTIFIER_random_fill,\r
45         0       /* Use generic outmost tag fetcher */\r
46 };\r
47 asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {\r
48         "OBJECT IDENTIFIER",\r
49         "OBJECT_IDENTIFIER",\r
50         &asn_OP_OBJECT_IDENTIFIER,\r
51         asn_DEF_OBJECT_IDENTIFIER_tags,\r
52         sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)\r
53             / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),\r
54         asn_DEF_OBJECT_IDENTIFIER_tags, /* Same as above */\r
55         sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)\r
56             / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),\r
57         { 0, 0, OBJECT_IDENTIFIER_constraint },\r
58         0, 0,   /* No members */\r
59         0       /* No specifics */\r
60 };\r
61 \r
62 int\r
63 OBJECT_IDENTIFIER_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,\r
64                              asn_app_constraint_failed_f *ctfailcb,\r
65                              void *app_key) {\r
66     const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;\r
67 \r
68         if(st && st->buf) {\r
69                 if(st->size < 1) {\r
70                         ASN__CTFAIL(app_key, td, sptr,\r
71                                 "%s: at least one numerical value "\r
72                                 "expected (%s:%d)",\r
73                                 td->name, __FILE__, __LINE__);\r
74                         return -1;\r
75                 }\r
76         } else {\r
77                 ASN__CTFAIL(app_key, td, sptr,\r
78                         "%s: value not given (%s:%d)",\r
79                         td->name, __FILE__, __LINE__);\r
80                 return -1;\r
81         }\r
82 \r
83         return 0;\r
84 }\r
85 \r
86 static ssize_t\r
87 OBJECT_IDENTIFIER_get_first_arcs(const uint8_t *arcbuf, size_t arcbuf_len,\r
88                                  asn_oid_arc_t *arc0, asn_oid_arc_t *arc1) {\r
89     asn_oid_arc_t value;\r
90 \r
91     ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(arcbuf, arcbuf_len, &value);\r
92     if(rd <= 0) return rd;\r
93 \r
94     if(value >= 80) {\r
95         *arc0 = 2;\r
96         *arc1 = value - 80;\r
97     } else if(value >= 40) {\r
98         *arc0 = 1;\r
99         *arc1 = value - 40;\r
100     } else {\r
101         *arc0 = 0;\r
102         *arc1 = value;\r
103     }\r
104 \r
105     return rd;\r
106 }\r
107 \r
108 ssize_t\r
109 OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, size_t arcbuf_len,\r
110                                  asn_oid_arc_t *ret_value) {\r
111     const uint8_t *b = arcbuf;\r
112     const uint8_t *arcend = arcbuf + arcbuf_len; /* End of arc */\r
113 \r
114     if(arcbuf == arcend) {\r
115         return 0;\r
116     } else {\r
117         asn_oid_arc_t accum;\r
118         asn_oid_arc_t upper_limit = (ASN_OID_ARC_MAX >> 7);\r
119         /* When the value reaches "upper_limit", it can take */\r
120         /* at most one more digit. If it exceeds "upper_limit" */\r
121         /* but there are more digits - it's an Overflow condition */\r
122         /* Gather all bits into the accumulator */\r
123         for(accum = 0; b < arcend; b++) {\r
124             accum = (accum << 7) | (*b & ~0x80);\r
125             if((*b & 0x80) == 0) { // no more digits\r
126                 if(accum <= ASN_OID_ARC_MAX) {\r
127                     *ret_value = accum;\r
128                     return 1 + (b - arcbuf);\r
129                 } else {\r
130                     errno = ERANGE; /* Overflow */\r
131                     return -1;\r
132                 }\r
133             } else { // to make sure we aren't wrapping around\r
134               if(accum > upper_limit) {\r
135                     errno = ERANGE; /* Overflow */\r
136                     return -1;\r
137               }\r
138             }\r
139         }\r
140         errno = EINVAL;\r
141         return -1;\r
142     }\r
143 \r
144 }\r
145 \r
146 static ssize_t\r
147 OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st,\r
148                              asn_app_consume_bytes_f *cb, void *app_key) {\r
149     char scratch[32];\r
150     asn_oid_arc_t arc0, arc1;\r
151     size_t produced = 0;\r
152     size_t off = 0;\r
153     ssize_t rd;\r
154     int ret;\r
155 \r
156     rd = OBJECT_IDENTIFIER_get_first_arcs(st->buf, st->size, &arc0, &arc1);\r
157     if(rd <= 0) {\r
158         return -1;\r
159     }\r
160 \r
161     ret = snprintf(scratch, sizeof(scratch), "%"PRIu32".%"PRIu32, arc0, arc1);\r
162     if(ret >= (ssize_t)sizeof(scratch)) {\r
163         return -1;\r
164     }\r
165     produced += ret;\r
166     if(cb(scratch, ret, app_key) < 0)\r
167         return -1;\r
168 \r
169     for(off = rd; ; ) {\r
170         asn_oid_arc_t arc;\r
171         rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off, st->size - off,\r
172                                               &arc);\r
173         if(rd < 0) {\r
174             return -1;\r
175         } else if(rd == 0) {\r
176             /* No more arcs. */\r
177             break;\r
178         } else {\r
179             off += rd;\r
180             assert(off <= st->size);\r
181             ret = snprintf(scratch, sizeof(scratch), ".%" PRIu32, arc);\r
182             if(ret >= (ssize_t)sizeof(scratch)) {\r
183                 return -1;\r
184             }\r
185             produced += ret;\r
186             if(cb(scratch, ret, app_key) < 0) return -1;\r
187         }\r
188     }\r
189 \r
190     if(off != st->size) {\r
191         ASN_DEBUG("Could not scan to the end of Object Identifier");\r
192         return -1;\r
193     }\r
194 \r
195         return produced;\r
196 }\r
197 \r
198 static enum xer_pbd_rval\r
199 OBJECT_IDENTIFIER__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,\r
200                                    const void *chunk_buf, size_t chunk_size) {\r
201     OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr;\r
202         const char *chunk_end = (const char *)chunk_buf + chunk_size;\r
203         const char *endptr;\r
204         asn_oid_arc_t s_arcs[10];\r
205         asn_oid_arc_t *arcs = s_arcs;\r
206         ssize_t num_arcs;\r
207         ssize_t ret;\r
208 \r
209         (void)td;\r
210 \r
211     num_arcs = OBJECT_IDENTIFIER_parse_arcs(\r
212         (const char *)chunk_buf, chunk_size, arcs,\r
213         sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);\r
214     if(num_arcs < 0) {\r
215                 /* Expecting more than zero arcs */\r
216                 return XPBD_BROKEN_ENCODING;\r
217         } else if(num_arcs == 0) {\r
218                 return XPBD_NOT_BODY_IGNORE;\r
219         }\r
220         assert(endptr == chunk_end);\r
221 \r
222         if((size_t)num_arcs > sizeof(s_arcs)/sizeof(s_arcs[0])) {\r
223                 arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(asn_oid_arc_t));\r
224                 if(!arcs) return XPBD_SYSTEM_FAILURE;\r
225         ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,\r
226                                            arcs, num_arcs, &endptr);\r
227         if(ret != num_arcs)\r
228                         return XPBD_SYSTEM_FAILURE;     /* assert?.. */\r
229         }\r
230 \r
231         /*\r
232          * Convert arcs into BER representation.\r
233          */\r
234         ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, num_arcs);\r
235         if(arcs != s_arcs) FREEMEM(arcs);\r
236 \r
237         return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;\r
238 }\r
239 \r
240 asn_dec_rval_t\r
241 OBJECT_IDENTIFIER_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,\r
242                              const asn_TYPE_descriptor_t *td, void **sptr,\r
243                              const char *opt_mname, const void *buf_ptr,\r
244                              size_t size) {\r
245     return xer_decode_primitive(opt_codec_ctx, td,\r
246                 sptr, sizeof(OBJECT_IDENTIFIER_t), opt_mname,\r
247                         buf_ptr, size, OBJECT_IDENTIFIER__xer_body_decode);\r
248 }\r
249 \r
250 asn_enc_rval_t\r
251 OBJECT_IDENTIFIER_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,\r
252                              int ilevel, enum xer_encoder_flags_e flags,\r
253                              asn_app_consume_bytes_f *cb, void *app_key) {\r
254     const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;\r
255     asn_enc_rval_t er = {0,0,0};\r
256 \r
257     (void)ilevel;\r
258     (void)flags;\r
259 \r
260     if(!st || !st->buf) {\r
261         ASN__ENCODE_FAILED;\r
262     }\r
263 \r
264     er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key);\r
265     if(er.encoded < 0) ASN__ENCODE_FAILED;\r
266 \r
267     ASN__ENCODED_OK(er);\r
268 }\r
269 \r
270 int\r
271 OBJECT_IDENTIFIER_print(const asn_TYPE_descriptor_t *td, const void *sptr,\r
272                         int ilevel, asn_app_consume_bytes_f *cb,\r
273                         void *app_key) {\r
274     const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;\r
275 \r
276         (void)td;       /* Unused argument */\r
277         (void)ilevel;   /* Unused argument */\r
278 \r
279         if(!st || !st->buf)\r
280                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;\r
281 \r
282         /* Dump preamble */\r
283         if(cb("{ ", 2, app_key) < 0)\r
284                 return -1;\r
285 \r
286     if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0) {\r
287         return -1;\r
288     }\r
289 \r
290     return (cb(" }", 2, app_key) < 0) ? -1 : 0;\r
291 }\r
292 \r
293 ssize_t\r
294 OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *st, asn_oid_arc_t *arcs,\r
295                            size_t arc_slots) {\r
296     asn_oid_arc_t arc0, arc1;\r
297     size_t num_arcs = 0;\r
298     size_t off;\r
299     ssize_t rd;\r
300 \r
301     if(!st || !st->buf) {\r
302         errno = EINVAL;\r
303         return -1;\r
304     }\r
305 \r
306     rd = OBJECT_IDENTIFIER_get_first_arcs(st->buf, st->size, &arc0, &arc1);\r
307     if(rd <= 0) {\r
308         return -1;\r
309     }\r
310     num_arcs = 2;\r
311     switch(arc_slots) {\r
312     default:\r
313     case 2:\r
314         arcs[1] = arc1;\r
315         /* Fall through */\r
316     case 1:\r
317         arcs[0] = arc0;\r
318         /* Fall through */\r
319     case 0:\r
320         break;\r
321     }\r
322 \r
323     for(off = rd; ; ) {\r
324         asn_oid_arc_t arc;\r
325         rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off, st->size - off,\r
326                                               &arc);\r
327         if(rd < 0) {\r
328             return -1;\r
329         } else if(rd == 0) {\r
330             /* No more arcs. */\r
331             break;\r
332         } else {\r
333             off += rd;\r
334             if(num_arcs < arc_slots) {\r
335                 arcs[num_arcs] = arc;\r
336             }\r
337             num_arcs++;\r
338         }\r
339     }\r
340 \r
341     if(off != st->size) {\r
342         return -1;\r
343     }\r
344 \r
345     return num_arcs;\r
346 }\r
347 \r
348 \r
349 /*\r
350  * Save the single value as an object identifier arc.\r
351  */\r
352 ssize_t\r
353 OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, size_t arcbuf_len,\r
354                                  asn_oid_arc_t value) {\r
355     /*\r
356          * The following conditions must hold:\r
357          * assert(arcbuf);\r
358          */\r
359     uint8_t scratch[((sizeof(value) * CHAR_BIT + 6) / 7)];\r
360     uint8_t *scratch_end = &scratch[sizeof(scratch)-1];\r
361     uint8_t *b;\r
362     size_t result_len;\r
363     uint8_t mask;\r
364 \r
365     for(b = scratch_end, mask = 0; ; mask = 0x80, b--) {\r
366         *b = mask | (value & 0x7f);\r
367         value >>= 7;\r
368         if(!value) {\r
369             break;\r
370         }\r
371     }\r
372 \r
373     result_len = (scratch_end - b) + 1;\r
374 \r
375     if(result_len > arcbuf_len) {\r
376         return -1;\r
377     }\r
378 \r
379     memcpy(arcbuf, b, result_len);\r
380 \r
381         return result_len;\r
382 }\r
383 \r
384 int\r
385 OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *st, const asn_oid_arc_t *arcs,\r
386                            size_t arc_slots) {\r
387     uint8_t *buf;\r
388     uint8_t *bp;\r
389     ssize_t wrote;\r
390     asn_oid_arc_t arc0;\r
391     asn_oid_arc_t arc1;\r
392     size_t size;\r
393     size_t i;\r
394 \r
395     if(!st || !arcs || arc_slots < 2) {\r
396         errno = EINVAL;\r
397                 return -1;\r
398         }\r
399 \r
400     arc0 = arcs[0];\r
401     arc1 = arcs[1];\r
402 \r
403         if(arc0 <= 1) {\r
404                 if(arc1 >= 40) {\r
405                         /* 8.19.4: At most 39 subsequent values (including 0) */\r
406                         errno = ERANGE;\r
407                         return -1;\r
408                 }\r
409     } else if(arc0 == 2) {\r
410         if(arc1 > ASN_OID_ARC_MAX - 80) {\r
411             errno = ERANGE;\r
412             return -1;\r
413         }\r
414     } else if(arc0 > 2) {\r
415         /* 8.19.4: Only three values are allocated from the root node */\r
416         errno = ERANGE;\r
417         return -1;\r
418     }\r
419 \r
420     /*\r
421          * After above tests it is known that the value of arc0 is completely\r
422          * trustworthy (0..2). However, the arc1's value is still meaningless.\r
423          */\r
424 \r
425     /*\r
426      * Roughly estimate the maximum size necessary to encode these arcs.\r
427      * This estimation implicitly takes in account the following facts,\r
428      * that cancel each other:\r
429      *  * the first two arcs are encoded in a single value.\r
430      *  * the first value may require more space (+1 byte)\r
431      *  * the value of the first arc which is in range (0..2)\r
432      */\r
433     size = ((sizeof(asn_oid_arc_t) * CHAR_BIT + 6) / 7) * arc_slots;\r
434     bp = buf = (uint8_t *)MALLOC(size + 1);\r
435     if(!buf) {\r
436         /* ENOMEM */\r
437         return -1;\r
438     }\r
439 \r
440     wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arc0 * 40 + arc1);\r
441     if(wrote <= 0) {\r
442         FREEMEM(buf);\r
443         return -1;\r
444     }\r
445     assert((size_t)wrote <= size);\r
446     bp += wrote;\r
447     size -= wrote;\r
448 \r
449     for(i = 2; i < arc_slots; i++) {\r
450                 wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arcs[i]);\r
451         if(wrote <= 0) {\r
452             FREEMEM(buf);\r
453             return -1;\r
454         }\r
455         assert((size_t)wrote <= size);\r
456         bp += wrote;\r
457         size -= wrote;\r
458     }\r
459 \r
460     /*\r
461          * Replace buffer.\r
462          */\r
463         st->size = bp - buf;\r
464         bp = st->buf;\r
465         st->buf = buf;\r
466         st->buf[st->size] = '\0';\r
467         if(bp) FREEMEM(bp);\r
468 \r
469         return 0;\r
470 }\r
471 \r
472 ssize_t\r
473 OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,\r
474                              asn_oid_arc_t *arcs, size_t arcs_count,\r
475                              const char **opt_oid_text_end) {\r
476     size_t num_arcs = 0;\r
477     const char *oid_end;\r
478         enum {\r
479                 ST_LEADSPACE,\r
480                 ST_TAILSPACE,\r
481                 ST_AFTERVALUE,  /* Next character ought to be '.' or a space */\r
482                 ST_WAITDIGITS   /* Next character is expected to be a digit */\r
483         } state = ST_LEADSPACE;\r
484 \r
485         if(!oid_text || oid_txt_length < -1 || (arcs_count && !arcs)) {\r
486                 if(opt_oid_text_end) *opt_oid_text_end = oid_text;\r
487                 errno = EINVAL;\r
488                 return -1;\r
489         }\r
490 \r
491         if(oid_txt_length == -1)\r
492                 oid_txt_length = strlen(oid_text);\r
493 \r
494 #define _OID_CAPTURE_ARC(oid_text, oid_end)                       \\r
495     do {                                                          \\r
496         const char *endp = oid_end;                               \\r
497         unsigned long value;                                      \\r
498         switch(asn_strtoul_lim(oid_text, &endp, &value)) {        \\r
499         case ASN_STRTOX_EXTRA_DATA:                               \\r
500         case ASN_STRTOX_OK:                                       \\r
501             if(value <= ASN_OID_ARC_MAX) {                        \\r
502                 if(num_arcs < arcs_count) arcs[num_arcs] = value; \\r
503                 num_arcs++;                                       \\r
504                 oid_text = endp - 1;                              \\r
505                 break;                                            \\r
506             }                                                     \\r
507             /* Fall through */                                    \\r
508         case ASN_STRTOX_ERROR_RANGE:                              \\r
509             if(opt_oid_text_end) *opt_oid_text_end = oid_text;    \\r
510             errno = ERANGE;                                       \\r
511             return -1;                                            \\r
512         case ASN_STRTOX_ERROR_INVAL:                              \\r
513         case ASN_STRTOX_EXPECT_MORE:                              \\r
514             if(opt_oid_text_end) *opt_oid_text_end = oid_text;    \\r
515             errno = EINVAL;                                       \\r
516             return -1;                                            \\r
517         }                                                         \\r
518     } while(0)\r
519 \r
520     for(oid_end = oid_text + oid_txt_length; oid_text<oid_end; oid_text++) {\r
521             switch(*oid_text) {\r
522             case 0x09: case 0x0a: case 0x0d: case 0x20: /* whitespace */\r
523                 switch(state) {\r
524                 case ST_LEADSPACE:\r
525                 case ST_TAILSPACE:\r
526                         continue;\r
527                 case ST_AFTERVALUE:\r
528                         state = ST_TAILSPACE;\r
529                         continue;\r
530                 case ST_WAITDIGITS:\r
531                         break;  /* Digits expected after ".", got whitespace */\r
532                 }\r
533                 break;\r
534             case 0x2e:  /* '.' */\r
535                 switch(state) {\r
536                 case ST_LEADSPACE:\r
537                 case ST_TAILSPACE:\r
538                 case ST_WAITDIGITS:\r
539                         if(opt_oid_text_end)\r
540                                 *opt_oid_text_end = oid_text;\r
541                         errno = EINVAL; /* Broken OID */\r
542                         return -1;\r
543                         break;\r
544                 case ST_AFTERVALUE:\r
545                         state = ST_WAITDIGITS;\r
546                         continue;\r
547                 }\r
548                 break;\r
549             case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:\r
550             case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:\r
551                 switch(state) {\r
552                 case ST_TAILSPACE:\r
553                 case ST_AFTERVALUE:\r
554                         if(opt_oid_text_end)\r
555                                 *opt_oid_text_end = oid_text;\r
556                         errno = EINVAL; /* "1. 1" => broken OID */\r
557                         return -1;\r
558                 case ST_LEADSPACE:\r
559                 case ST_WAITDIGITS:\r
560                         _OID_CAPTURE_ARC(oid_text, oid_end);\r
561                         state = ST_AFTERVALUE;\r
562                         continue;\r
563                 }\r
564                 break;\r
565             default:\r
566                 /* Unexpected symbols */\r
567                 state = ST_WAITDIGITS;\r
568                 break;\r
569             } /* switch() */\r
570             break;\r
571         } /* for() */\r
572 \r
573 \r
574         if(opt_oid_text_end) *opt_oid_text_end = oid_text;\r
575 \r
576         /* Finalize last arc */\r
577         switch(state) {\r
578         case ST_LEADSPACE:\r
579                 return 0; /* No OID found in input data */\r
580         case ST_WAITDIGITS:\r
581                 errno = EINVAL; /* Broken OID */\r
582                 return -1;\r
583         case ST_AFTERVALUE:\r
584         case ST_TAILSPACE:\r
585                 return num_arcs;\r
586         }\r
587 \r
588         errno = EINVAL; /* Broken OID */\r
589         return -1;\r
590 }\r
591 \r
592 /*\r
593  * Generate values from the list of interesting values, or just a random\r
594  * value up to the upper limit.\r
595  */\r
596 static asn_oid_arc_t\r
597 OBJECT_IDENTIFIER__biased_random_arc(asn_oid_arc_t upper_bound) {\r
598     const asn_oid_arc_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};\r
599     size_t idx;\r
600 \r
601     switch(asn_random_between(0, 2)) {\r
602     case 0:\r
603         idx = asn_random_between(0, sizeof(values) / sizeof(values[0]) - 1);\r
604         if(values[idx] < upper_bound) {\r
605             return values[idx];\r
606         }\r
607         /* Fall through */\r
608     case 1:\r
609         return asn_random_between(0, upper_bound);\r
610     case 2:\r
611     default:\r
612         return upper_bound;\r
613     }\r
614 }\r
615 \r
616 asn_random_fill_result_t\r
617 OBJECT_IDENTIFIER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,\r
618                               const asn_encoding_constraints_t *constraints,\r
619                               size_t max_length) {\r
620     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};\r
621     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};\r
622     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};\r
623     OBJECT_IDENTIFIER_t *st;\r
624     asn_oid_arc_t arcs[5];\r
625     size_t arcs_len = asn_random_between(2, 5);\r
626     size_t i;\r
627 \r
628     (void)constraints;\r
629 \r
630     if(max_length < arcs_len) return result_skipped;\r
631 \r
632     if(*sptr) {\r
633         st = *sptr;\r
634     } else {\r
635         st = CALLOC(1, sizeof(*st));\r
636     }\r
637 \r
638     arcs[0] = asn_random_between(0, 2);\r
639     arcs[1] = OBJECT_IDENTIFIER__biased_random_arc(\r
640         arcs[0] <= 1 ? 39 : (ASN_OID_ARC_MAX - 80));\r
641     for(i = 2; i < arcs_len; i++) {\r
642         arcs[i] = OBJECT_IDENTIFIER__biased_random_arc(ASN_OID_ARC_MAX);\r
643     }\r
644 \r
645     if(OBJECT_IDENTIFIER_set_arcs(st, arcs, arcs_len)) {\r
646         if(st != *sptr) {\r
647             ASN_STRUCT_FREE(*td, st);\r
648         }\r
649         return result_failed;\r
650     }\r
651 \r
652     *sptr = st;\r
653 \r
654     result_ok.length = st->size;\r
655     return result_ok;\r
656 }\r