1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * Stream parser for RFC8949 CBOR
25 */
26
27 #include "private-lib-core.h"
28 #include <string.h>
29 #include <stdio.h>
30
31 #if defined(LWS_WITH_CBOR_FLOAT)
32 #include <math.h>
33 #endif
34
35 #define lwsl_lecp lwsl_debug
36
37 static const char * const parser_errs[] = {
38 "",
39 "",
40 "Bad CBOR coding",
41 "Unknown",
42 "Parser callback errored (see earlier error)",
43 "Overflow"
44 };
45
46 enum lecp_states {
47 LECP_OPC,
48 LECP_COLLECT,
49 LECP_SIMPLEX8,
50 LECP_COLLATE,
51 LECP_ONLY_SAME
52 };
53
54 void
lecp_construct(struct lecp_ctx * ctx,lecp_callback cb,void * user,const char * const * paths,unsigned char count_paths)55 lecp_construct(struct lecp_ctx *ctx, lecp_callback cb, void *user,
56 const char * const *paths, unsigned char count_paths)
57 {
58 uint16_t x = 0x1234;
59
60 memset(ctx, 0, sizeof(*ctx) - sizeof(ctx->buf));
61
62 ctx->user = user;
63 ctx->pst[0].cb = cb;
64 ctx->pst[0].paths = paths;
65 ctx->pst[0].count_paths = count_paths;
66 ctx->be = *((uint8_t *)&x) == 0x12;
67
68 ctx->st[0].s = LECP_OPC;
69
70 ctx->pst[0].cb(ctx, LECPCB_CONSTRUCTED);
71 }
72
73 void
lecp_destruct(struct lecp_ctx * ctx)74 lecp_destruct(struct lecp_ctx *ctx)
75 {
76 /* no allocations... just let callback know what it happening */
77 if (ctx->pst[0].cb)
78 ctx->pst[0].cb(ctx, LECPCB_DESTRUCTED);
79 }
80
81 void
lecp_change_callback(struct lecp_ctx * ctx,lecp_callback cb)82 lecp_change_callback(struct lecp_ctx *ctx, lecp_callback cb)
83 {
84 ctx->pst[0].cb(ctx, LECPCB_DESTRUCTED);
85 ctx->pst[0].cb = cb;
86 ctx->pst[0].cb(ctx, LECPCB_CONSTRUCTED);
87 }
88
89
90 const char *
lecp_error_to_string(int e)91 lecp_error_to_string(int e)
92 {
93 if (e > 0)
94 e = 0;
95 else
96 e = -e;
97
98 if (e >= (int)LWS_ARRAY_SIZE(parser_errs))
99 return "Unknown error";
100
101 return parser_errs[e];
102 }
103
104 static void
ex(struct lecp_ctx * ctx,void * _start,size_t len)105 ex(struct lecp_ctx *ctx, void *_start, size_t len)
106 {
107 struct _lecp_stack *st = &ctx->st[ctx->sp];
108 uint8_t *start = (uint8_t *)_start;
109
110 st->s = LECP_COLLECT;
111 st->collect_rem = (uint8_t)len;
112
113 if (ctx->be)
114 ctx->collect_tgt = start;
115 else
116 ctx->collect_tgt = start + len - 1;
117 }
118
119 static void
lecp_check_path_match(struct lecp_ctx * ctx)120 lecp_check_path_match(struct lecp_ctx *ctx)
121 {
122 const char *p, *q;
123 size_t s = sizeof(char *);
124 int n;
125
126 if (ctx->path_stride)
127 s = ctx->path_stride;
128
129 /* we only need to check if a match is not active */
130 for (n = 0; !ctx->path_match &&
131 n < ctx->pst[ctx->pst_sp].count_paths; n++) {
132 ctx->wildcount = 0;
133 p = ctx->path;
134
135 q = *((char **)(((char *)ctx->pst[ctx->pst_sp].paths) +
136 ((unsigned int)n * s)));
137
138 while (*p && *q) {
139 if (*q != '*') {
140 if (*p != *q)
141 break;
142 p++;
143 q++;
144 continue;
145 }
146 ctx->wild[ctx->wildcount++] =
147 (uint16_t)lws_ptr_diff_size_t(p, ctx->path);
148 q++;
149 /*
150 * if * has something after it, match to .
151 * if ends with *, eat everything.
152 * This implies match sequences must be ordered like
153 * x.*.*
154 * x.*
155 * if both options are possible
156 */
157 while (*p && (*p != '.' || !*q))
158 p++;
159 }
160 if (*p || *q)
161 continue;
162
163 ctx->path_match = (uint8_t)(n + 1);
164 ctx->path_match_len = ctx->pst[ctx->pst_sp].ppos;
165 return;
166 }
167
168 if (!ctx->path_match)
169 ctx->wildcount = 0;
170 }
171
172 int
lecp_push(struct lecp_ctx * ctx,char s_start,char s_end,char state)173 lecp_push(struct lecp_ctx *ctx, char s_start, char s_end, char state)
174 {
175 struct _lecp_stack *st = &ctx->st[ctx->sp];
176
177 if (ctx->sp + 1 == LWS_ARRAY_SIZE(ctx->st))
178 return LECP_STACK_OVERFLOW;
179
180 if (s_start && ctx->pst[ctx->pst_sp].cb(ctx, s_start))
181 return LECP_REJECT_CALLBACK;
182
183 lwsl_lecp("%s: pushing from sp %d, parent "
184 "(opc %d, indet %d, collect_rem %d)\n",
185 __func__, ctx->sp, st->opcode >> 5, st->indet,
186 (int)st->collect_rem);
187
188
189 st->pop_iss = s_end; /* issue this when we pop back here */
190 ctx->st[ctx->sp + 1] = *st;
191 ctx->sp++;
192 st++;
193
194 st->s = state;
195 st->collect_rem = 0;
196 st->intermediate = 0;
197 st->indet = 0;
198 st->ordinal = 0;
199 st->send_new_array_item = 0;
200 st->barrier = 0;
201
202 return 0;
203 }
204
205 int
lecp_pop(struct lecp_ctx * ctx)206 lecp_pop(struct lecp_ctx *ctx)
207 {
208 struct _lecp_stack *st;
209
210 assert(ctx->sp);
211 ctx->sp--;
212
213 st = &ctx->st[ctx->sp];
214
215 if (st->pop_iss == LECPCB_ARRAY_END) {
216 assert(ctx->ipos);
217 ctx->ipos--;
218 }
219
220 ctx->pst[ctx->pst_sp].ppos = st->p;
221 ctx->path[st->p] = '\0';
222 lecp_check_path_match(ctx);
223
224 lwsl_lecp("%s: popping to sp %d, parent "
225 "(opc %d, indet %d, collect_rem %d)\n",
226 __func__, ctx->sp, st->opcode >> 5, st->indet,
227 (int)st->collect_rem);
228
229 if (st->pop_iss && ctx->pst[ctx->pst_sp].cb(ctx, st->pop_iss))
230 return LECP_REJECT_CALLBACK;
231
232 return 0;
233 }
234
235 static struct _lecp_stack *
lwcp_st_parent(struct lecp_ctx * ctx)236 lwcp_st_parent(struct lecp_ctx *ctx)
237 {
238 assert(ctx->sp);
239
240 return &ctx->st[ctx->sp - 1];
241 }
242
243 int
lwcp_completed(struct lecp_ctx * ctx,char indet)244 lwcp_completed(struct lecp_ctx *ctx, char indet)
245 {
246 int r, il = ctx->ipos;
247
248 ctx->st[ctx->sp].s = LECP_OPC;
249
250 while (ctx->sp && !ctx->st[ctx->sp].barrier) {
251 struct _lecp_stack *parent = lwcp_st_parent(ctx);
252
253 lwsl_lecp("%s: sp %d, parent "
254 "(opc %d, indet %d, collect_rem %d)\n",
255 __func__, ctx->sp, parent->opcode >> 5, parent->indet,
256 (int)parent->collect_rem);
257
258 parent->ordinal++;
259 if (parent->opcode == LWS_CBOR_MAJTYP_ARRAY) {
260 assert(il);
261 il--;
262 ctx->i[il]++;
263 if (!parent->send_new_array_item) {
264 if (ctx->pst[ctx->pst_sp].cb(ctx,
265 LECPCB_ARRAY_ITEM_END))
266 return LECP_REJECT_CALLBACK;
267 parent->send_new_array_item = 1;
268 }
269 }
270
271 if (!indet && parent->indet) {
272 lwsl_lecp("%s: abandoning walk as parent needs indet\n", __func__);
273 break;
274 }
275
276 if (!parent->indet && parent->collect_rem) {
277 parent->collect_rem--;
278 lwsl_lecp("%s: sp %d, parent (opc %d, indet %d, collect_rem -> %d)\n",
279 __func__, ctx->sp, parent->opcode >> 5, parent->indet, (int)parent->collect_rem);
280
281 if (parent->collect_rem) {
282 /* more items to come */
283 if (parent->opcode == LWS_CBOR_MAJTYP_ARRAY)
284 parent->send_new_array_item = 1;
285 break;
286 }
287 }
288
289 lwsl_lecp("%s: parent (opc %d) collect_rem became zero\n", __func__, parent->opcode >> 5);
290
291 ctx->st[ctx->sp - 1].s = LECP_OPC;
292 r = lecp_pop(ctx);
293 if (r)
294 return r;
295 indet = 0;
296 }
297
298 return 0;
299 }
300
301 static int
lwcp_is_indet_string(struct lecp_ctx * ctx)302 lwcp_is_indet_string(struct lecp_ctx *ctx)
303 {
304 if (ctx->st[ctx->sp].indet)
305 return 1;
306
307 if (!ctx->sp)
308 return 0;
309
310 if (lwcp_st_parent(ctx)->opcode != LWS_CBOR_MAJTYP_BSTR &&
311 lwcp_st_parent(ctx)->opcode != LWS_CBOR_MAJTYP_TSTR)
312 return 0;
313
314 if (ctx->st[ctx->sp - 1].indet)
315 return 1;
316
317 return 0;
318 }
319
320 static int
report_raw_cbor(struct lecp_ctx * ctx)321 report_raw_cbor(struct lecp_ctx *ctx)
322 {
323 struct _lecp_parsing_stack *pst = &ctx->pst[ctx->pst_sp];
324
325 if (!ctx->cbor_pos)
326 return 0;
327
328 if (pst->cb(ctx, LECPCB_LITERAL_CBOR))
329 return 1;
330
331 ctx->cbor_pos = 0;
332
333 return 0;
334 }
335
336 void
lecp_parse_report_raw(struct lecp_ctx * ctx,int on)337 lecp_parse_report_raw(struct lecp_ctx *ctx, int on)
338 {
339 ctx->literal_cbor_report = (uint8_t)on;
340 report_raw_cbor(ctx);
341 }
342
343 int
lecp_parse_map_is_key(struct lecp_ctx * ctx)344 lecp_parse_map_is_key(struct lecp_ctx *ctx)
345 {
346 return lwcp_st_parent(ctx)->opcode == LWS_CBOR_MAJTYP_MAP &&
347 !(lwcp_st_parent(ctx)->ordinal & 1);
348 }
349
350 int
lecp_parse_subtree(struct lecp_ctx * ctx,const uint8_t * in,size_t len)351 lecp_parse_subtree(struct lecp_ctx *ctx, const uint8_t *in, size_t len)
352 {
353 struct _lecp_stack *st = &ctx->st[++ctx->sp];
354 int n;
355
356 st->s = 0;
357 st->collect_rem = 0;
358 st->intermediate = 0;
359 st->indet = 0;
360 st->ordinal = 0;
361 st->send_new_array_item = 0;
362 st->barrier = 1;
363
364 n = lecp_parse(ctx, in, len);
365 ctx->sp--;
366
367 return n;
368 }
369
370 int
lecp_parse(struct lecp_ctx * ctx,const uint8_t * cbor,size_t len)371 lecp_parse(struct lecp_ctx *ctx, const uint8_t *cbor, size_t len)
372 {
373 size_t olen = len;
374 int ret;
375
376 while (len--) {
377 struct _lecp_parsing_stack *pst = &ctx->pst[ctx->pst_sp];
378 struct _lecp_stack *st = &ctx->st[ctx->sp];
379 uint8_t c, sm, o;
380 char to;
381
382 c = *cbor++;
383
384 /*
385 * for, eg, cose_sign, we sometimes need to collect subtrees of
386 * raw CBOR. Report buffers of it via the callback if we filled
387 * the buffer, or we stopped collecting.
388 */
389
390 if (ctx->literal_cbor_report) {
391 ctx->cbor[ctx->cbor_pos++] = c;
392 if (ctx->cbor_pos == sizeof(ctx->cbor) &&
393 report_raw_cbor(ctx))
394 goto reject_callback;
395 }
396
397 switch (st->s) {
398 /*
399 * We're getting the nex opcode
400 */
401 case LECP_OPC:
402 st->opcode = ctx->item.opcode = c & LWS_CBOR_MAJTYP_MASK;
403 sm = c & LWS_CBOR_SUBMASK;
404 to = 0;
405
406 lwsl_lecp("%s: %d: OPC %d|%d\n", __func__, ctx->sp,
407 c >> 5, sm);
408
409 if (c != 0xff && ctx->sp &&
410 ctx->st[ctx->sp - 1].send_new_array_item) {
411 ctx->st[ctx->sp - 1].send_new_array_item = 0;
412 if (ctx->pst[ctx->pst_sp].cb(ctx,
413 LECPCB_ARRAY_ITEM_START))
414 goto reject_callback;
415 }
416
417 switch (st->opcode) {
418 case LWS_CBOR_MAJTYP_UINT:
419 ctx->present = LECPCB_VAL_NUM_UINT;
420 if (sm < LWS_CBOR_1) {
421 ctx->item.u.i64 = (int64_t)sm;
422 goto issue;
423 }
424 goto i2;
425
426 case LWS_CBOR_MAJTYP_INT_NEG:
427 ctx->present = LECPCB_VAL_NUM_INT;
428 if (sm < 24) {
429 ctx->item.u.i64 = (-1ll) - (int64_t)sm;
430 goto issue;
431 }
432 i2:
433 if (sm >= LWS_CBOR_RESERVED)
434 goto bad_coding;
435 ctx->item.u.u64 = 0;
436 o = (uint8_t)(1 << (sm - LWS_CBOR_1));
437 ex(ctx, (uint8_t *)&ctx->item.u.u64, o);
438 break;
439
440 case LWS_CBOR_MAJTYP_BSTR:
441 to = LECPCB_VAL_BLOB_END - LECPCB_VAL_STR_END;
442
443 /* fallthru */
444
445 case LWS_CBOR_MAJTYP_TSTR:
446 /*
447 * The first thing is the string length, it's
448 * going to either be a byte count for the
449 * string or the indefinite length marker
450 * followed by determinite-length chunks of the
451 * same MAJTYP
452 */
453
454 ctx->npos = 0;
455 ctx->buf[0] = '\0';
456
457 if (!sm) {
458 if ((!ctx->sp || (ctx->sp &&
459 !ctx->st[ctx->sp - 1].intermediate)) &&
460 pst->cb(ctx, (char)(LECPCB_VAL_STR_START + to)))
461 goto reject_callback;
462
463 if (pst->cb(ctx, (char)(LECPCB_VAL_STR_END + to)))
464 goto reject_callback;
465 lwcp_completed(ctx, 0);
466 break;
467 }
468
469 if (sm < LWS_CBOR_1) {
470 ctx->item.u.u64 = (uint64_t)sm;
471 if ((!ctx->sp || (ctx->sp &&
472 !ctx->st[ctx->sp - 1].intermediate)) &&
473 pst->cb(ctx, (char)(LECPCB_VAL_STR_START + to)))
474 goto reject_callback;
475
476 st->indet = 0;
477 st->collect_rem = sm;
478 st->s = LECP_COLLATE;
479 break;
480 }
481
482 if (sm < LWS_CBOR_RESERVED)
483 goto i2;
484
485 if (sm != LWS_CBOR_INDETERMINITE)
486 goto bad_coding;
487
488 if ((!ctx->sp || (ctx->sp &&
489 !ctx->st[ctx->sp - 1].intermediate)) &&
490 pst->cb(ctx, (char)(LECPCB_VAL_STR_START + to)))
491 goto reject_callback;
492
493 st->indet = 1;
494
495 st->p = pst->ppos;
496 lecp_push(ctx, 0, (char)(LECPCB_VAL_STR_END + to),
497 LECP_ONLY_SAME);
498 break;
499
500 case LWS_CBOR_MAJTYP_ARRAY:
501 ctx->npos = 0;
502 ctx->buf[0] = '\0';
503
504 if (pst->ppos + 3u >= sizeof(ctx->path))
505 goto reject_overflow;
506
507 st->p = pst->ppos;
508 ctx->path[pst->ppos++] = '[';
509 ctx->path[pst->ppos++] = ']';
510 ctx->path[pst->ppos] = '\0';
511
512 lecp_check_path_match(ctx);
513
514 if (ctx->ipos + 1u >= LWS_ARRAY_SIZE(ctx->i))
515 goto reject_overflow;
516
517 ctx->i[ctx->ipos++] = 0;
518
519 if (pst->cb(ctx, LECPCB_ARRAY_START))
520 goto reject_callback;
521
522 if (!sm) {
523 if (pst->cb(ctx, LECPCB_ARRAY_END))
524 goto reject_callback;
525 pst->ppos = st->p;
526 ctx->path[pst->ppos] = '\0';
527 if (ctx->ipos)
528 ctx->ipos--;
529 lecp_check_path_match(ctx);
530 lwcp_completed(ctx, 0);
531 break;
532 }
533
534 ctx->st[ctx->sp].send_new_array_item = 1;
535
536 if (sm < LWS_CBOR_1) {
537 st->indet = 0;
538 st->collect_rem = sm;
539 goto push_a;
540 }
541
542 if (sm < LWS_CBOR_RESERVED)
543 goto i2;
544
545 if (sm != LWS_CBOR_INDETERMINITE)
546 goto bad_coding;
547
548 st->indet = 1;
549 push_a:
550 lecp_push(ctx, 0, LECPCB_ARRAY_END, LECP_OPC);
551 break;
552
553 case LWS_CBOR_MAJTYP_MAP:
554 ctx->npos = 0;
555 ctx->buf[0] = '\0';
556
557 if (pst->ppos + 1u >= sizeof(ctx->path))
558 goto reject_overflow;
559
560 st->p = pst->ppos;
561 ctx->path[pst->ppos++] = '.';
562 ctx->path[pst->ppos] = '\0';
563
564 lecp_check_path_match(ctx);
565
566 if (pst->cb(ctx, LECPCB_OBJECT_START))
567 goto reject_callback;
568
569 if (!sm) {
570 if (pst->cb(ctx, LECPCB_OBJECT_END))
571 goto reject_callback;
572 pst->ppos = st->p;
573 ctx->path[pst->ppos] = '\0';
574 lecp_check_path_match(ctx);
575 lwcp_completed(ctx, 0);
576 break;
577 }
578 if (sm < LWS_CBOR_1) {
579 st->indet = 0;
580 st->collect_rem = (uint64_t)(sm * 2);
581 goto push_m;
582 }
583
584 if (sm < LWS_CBOR_RESERVED)
585 goto i2;
586
587 if (sm != LWS_CBOR_INDETERMINITE)
588 goto bad_coding;
589
590 st->indet = 1;
591 push_m:
592 lecp_push(ctx, 0, LECPCB_OBJECT_END, LECP_OPC);
593 break;
594
595 case LWS_CBOR_MAJTYP_TAG:
596 /* tag has one or another kind of int first */
597 if (sm < LWS_CBOR_1) {
598 /*
599 * We have a literal tag number, push
600 * to decode the tag body
601 */
602 ctx->item.u.u64 = st->tag = (uint64_t)sm;
603 goto start_tag_enclosure;
604 }
605 /*
606 * We have to do more stuff to get the tag
607 * number...
608 */
609 goto i2;
610
611 case LWS_CBOR_MAJTYP_FLOAT:
612 /*
613 * This can also be a bunch of specials as well
614 * as sizes of float...
615 */
616 sm = c & LWS_CBOR_SUBMASK;
617
618 switch (sm) {
619 case LWS_CBOR_SWK_FALSE:
620 ctx->present = LECPCB_VAL_FALSE;
621 goto issue;
622
623 case LWS_CBOR_SWK_TRUE:
624 ctx->present = LECPCB_VAL_TRUE;
625 goto issue;
626
627 case LWS_CBOR_SWK_NULL:
628 ctx->present = LECPCB_VAL_NULL;
629 goto issue;
630
631 case LWS_CBOR_SWK_UNDEFINED:
632 ctx->present = LECPCB_VAL_UNDEFINED;
633 goto issue;
634
635 case LWS_CBOR_M7_SUBTYP_SIMPLE_X8:
636 st->s = LECP_SIMPLEX8;
637 break;
638
639 case LWS_CBOR_M7_SUBTYP_FLOAT16:
640 ctx->present = LECPCB_VAL_FLOAT16;
641 ex(ctx, &ctx->item.u.hf, 2);
642 break;
643
644 case LWS_CBOR_M7_SUBTYP_FLOAT32:
645 ctx->present = LECPCB_VAL_FLOAT32;
646 ex(ctx, &ctx->item.u.f, 4);
647 break;
648
649 case LWS_CBOR_M7_SUBTYP_FLOAT64:
650 ctx->present = LECPCB_VAL_FLOAT64;
651 ex(ctx, &ctx->item.u.d, 8);
652 break;
653
654 case LWS_CBOR_M7_BREAK:
655 if (!ctx->sp ||
656 !ctx->st[ctx->sp - 1].indet)
657 goto bad_coding;
658
659 lwcp_completed(ctx, 1);
660 break;
661
662 default:
663 /* handle as simple */
664 ctx->item.u.u64 = (uint64_t)sm;
665 if (pst->cb(ctx, LECPCB_VAL_SIMPLE))
666 goto reject_callback;
667 break;
668 }
669 break;
670 }
671 break;
672
673 /*
674 * We're collecting int / float pieces
675 */
676 case LECP_COLLECT:
677 if (ctx->be)
678 *ctx->collect_tgt++ = c;
679 else
680 *ctx->collect_tgt-- = c;
681
682 if (--st->collect_rem)
683 break;
684
685 /*
686 * We collected whatever it was...
687 */
688
689 ctx->npos = 0;
690 ctx->buf[0] = '\0';
691
692 switch (st->opcode) {
693 case LWS_CBOR_MAJTYP_BSTR:
694 case LWS_CBOR_MAJTYP_TSTR:
695 st->collect_rem = ctx->item.u.u64;
696 if ((!ctx->sp || (ctx->sp &&
697 !ctx->st[ctx->sp - 1].intermediate)) &&
698 pst->cb(ctx, (char)((st->opcode ==
699 LWS_CBOR_MAJTYP_TSTR) ?
700 LECPCB_VAL_STR_START :
701 LECPCB_VAL_BLOB_START)))
702 goto reject_callback;
703 st->s = LECP_COLLATE;
704 break;
705
706 case LWS_CBOR_MAJTYP_ARRAY:
707 st->collect_rem = ctx->item.u.u64;
708 lecp_push(ctx, 0, LECPCB_ARRAY_END, LECP_OPC);
709 break;
710
711 case LWS_CBOR_MAJTYP_MAP:
712 st->collect_rem = ctx->item.u.u64 * 2;
713 lecp_push(ctx, 0, LECPCB_OBJECT_END, LECP_OPC);
714 break;
715
716 case LWS_CBOR_MAJTYP_TAG:
717 st->tag = ctx->item.u.u64;
718 goto start_tag_enclosure;
719
720 default:
721 /*
722 * ... then issue what we collected as a
723 * literal
724 */
725
726 if (st->opcode == LWS_CBOR_MAJTYP_INT_NEG)
727 ctx->item.u.i64 = (-1ll) - ctx->item.u.i64;
728
729 goto issue;
730 }
731 break;
732
733 case LECP_SIMPLEX8:
734 /*
735 * Extended SIMPLE byte for 7|24 opcode, no uses
736 * for it in RFC8949
737 */
738 if (c <= LWS_CBOR_INDETERMINITE)
739 /*
740 * Duplication of implicit simple values is
741 * denied by RFC8949 3.3
742 */
743 goto bad_coding;
744
745 ctx->item.u.u64 = (uint64_t)c;
746 if (pst->cb(ctx, LECPCB_VAL_SIMPLE))
747 goto reject_callback;
748
749 lwcp_completed(ctx, 0);
750 break;
751
752 case LECP_COLLATE:
753 /*
754 * let's grab b/t string content into the context
755 * buffer, and issue chunks from there
756 */
757
758 ctx->buf[ctx->npos++] = (char)c;
759 if (st->collect_rem)
760 st->collect_rem--;
761
762 /* spill at chunk boundaries, or if we filled the buf */
763 if (ctx->npos != sizeof(ctx->buf) - 1 &&
764 st->collect_rem)
765 break;
766
767 /* spill */
768 ctx->buf[ctx->npos] = '\0';
769
770 /* if it's a map name, deal with the path */
771 if (ctx->sp && lecp_parse_map_is_key(ctx)) {
772 if (lwcp_st_parent(ctx)->ordinal)
773 pst->ppos = st->p;
774 st->p = pst->ppos;
775 if (pst->ppos + ctx->npos > sizeof(ctx->path))
776 goto reject_overflow;
777 memcpy(&ctx->path[pst->ppos], ctx->buf,
778 (size_t)(ctx->npos + 1));
779 pst->ppos = (uint8_t)(pst->ppos + ctx->npos);
780 lecp_check_path_match(ctx);
781 }
782
783 to = 0;
784 if (ctx->item.opcode == LWS_CBOR_MAJTYP_BSTR)
785 to = LECPCB_VAL_BLOB_END - LECPCB_VAL_STR_END;
786
787 o = (uint8_t)(LECPCB_VAL_STR_END + to);
788 c = (st->collect_rem /* more to come at this layer */ ||
789 /* we or direct parent is indeterminite */
790 lwcp_is_indet_string(ctx));
791
792 if (ctx->sp)
793 ctx->st[ctx->sp - 1].intermediate = !!c;
794 if (c)
795 o--;
796
797 if (pst->cb(ctx, (char)o))
798 goto reject_callback;
799 ctx->npos = 0;
800 ctx->buf[0] = '\0';
801
802 if (ctx->sp && lwcp_st_parent(ctx)->indet)
803 st->s = LECP_OPC;
804 if (o == LECPCB_VAL_STR_END + to)
805 lwcp_completed(ctx, 0);
806
807 break;
808
809 case LECP_ONLY_SAME:
810 /*
811 * deterministic sized chunks same MAJTYP as parent
812 * level only (BSTR and TSTR frags inside interderminite
813 * BSTR or TSTR)
814 *
815 * Clean end when we see M7|31
816 */
817 if (!ctx->sp) {
818 /*
819 * We should only come here by pushing on stack
820 */
821 assert(0);
822 return LECP_STACK_OVERFLOW;
823 }
824
825 if (c == (LWS_CBOR_MAJTYP_FLOAT | LWS_CBOR_M7_BREAK)) {
826 /* if's the end of an interdetminite list */
827 if (!ctx->sp || !ctx->st[ctx->sp - 1].indet)
828 /*
829 * Can't have a break without an
830 * indeterminite parent
831 */
832 goto bad_coding;
833
834 if (lwcp_completed(ctx, 1))
835 goto reject_callback;
836 break;
837 }
838
839 if (st->opcode != lwcp_st_parent(ctx)->opcode)
840 /*
841 * Fragments have to be of the same type as the
842 * outer opcode
843 */
844 goto bad_coding;
845
846 sm = c & LWS_CBOR_SUBMASK;
847
848 if (sm == LWS_CBOR_INDETERMINITE)
849 /* indeterminite length frags not allowed */
850 goto bad_coding;
851
852 if (sm < LWS_CBOR_1) {
853 st->indet = 0;
854 st->collect_rem = (uint64_t)sm;
855 st->s = LECP_COLLATE;
856 break;
857 }
858
859 if (sm >= LWS_CBOR_RESERVED)
860 goto bad_coding;
861
862 goto i2;
863
864 default:
865 assert(0);
866 return -1;
867 }
868
869 continue;
870
871 start_tag_enclosure:
872 st->p = pst->ppos;
873 ret = lecp_push(ctx, LECPCB_TAG_START, LECPCB_TAG_END, LECP_OPC);
874 if (ret)
875 return ret;
876
877 continue;
878
879 issue:
880 if (ctx->item.opcode == LWS_CBOR_MAJTYP_TAG) {
881 st->tag = ctx->item.u.u64;
882 goto start_tag_enclosure;
883 }
884
885 /* we are just a number */
886
887 if (pst->cb(ctx, ctx->present))
888 goto reject_callback;
889
890 lwcp_completed(ctx, 0);
891
892 }
893
894 ctx->used_in = olen - len;
895
896 if (!ctx->sp && ctx->st[0].s == LECP_OPC)
897 return 0;
898
899 return LECP_CONTINUE;
900
901 reject_overflow:
902 ret = LECP_STACK_OVERFLOW;
903 goto reject;
904
905 bad_coding:
906 ret = LECP_REJECT_BAD_CODING;
907 goto reject;
908
909 reject_callback:
910 ret = LECP_REJECT_CALLBACK;
911
912 reject:
913 ctx->pst[ctx->pst_sp].cb(ctx, LECPCB_FAILED);
914
915 return ret;
916 }
917
918
919
920 void
lws_lec_init(lws_lec_pctx_t * ctx,uint8_t * buf,size_t len)921 lws_lec_init(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len)
922 {
923 memset(ctx, 0, sizeof(*ctx));
924 ctx->start = ctx->buf = buf;
925 ctx->end = ctx->start + len;
926 ctx->fmt_pos = 0;
927 }
928
929 void
lws_lec_setbuf(lws_lec_pctx_t * ctx,uint8_t * buf,size_t len)930 lws_lec_setbuf(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len)
931 {
932 ctx->start = ctx->buf = buf;
933 ctx->end = ctx->start + len;
934 ctx->used = 0;
935 ctx->vaa_pos = 0;
936 }
937
938 enum lws_lec_pctx_ret
lws_lec_printf(lws_lec_pctx_t * ctx,const char * format,...)939 lws_lec_printf(lws_lec_pctx_t *ctx, const char *format, ...)
940 {
941 enum lws_lec_pctx_ret r;
942 va_list ap;
943
944 va_start(ap, format);
945 r = lws_lec_vsprintf(ctx, format, ap);
946 va_end(ap);
947
948 return r;
949 }
950
951 /*
952 * Report how many next-level elements inbetween fmt[0] and the matching
953 * closure, eg, [] returns 0, [123] would return 1, [123,456] returns 2, and
954 * [123,{'a':[123,456]}] returns 2. Counts for { } maps are in pairs, ie,
955 * {'a':1, 'b': 2} returns 2
956 *
957 * If there is no closure in the string it returns -1
958 *
959 * We use this to figure out if we should use indeterminite lengths or specific
960 * lengths for items in the format string
961 */
962
963 #define bump(_r) count[sp]++
964 //; lwsl_notice("%s: count[%d] -> %d\n", _r, sp, count[sp])
965
966 static int
format_scan(const char * fmt)967 format_scan(const char *fmt)
968 {
969 char stack[12], literal = 0, numeric = 0;
970 int count[12], sp = 0, pc = 0, swallow = 0;
971
972 literal = *fmt == '\'';
973 stack[sp] = *fmt++;
974 count[sp] = 0;
975
976 // lwsl_notice("%s: start %s\n", __func__, fmt - 1);
977
978 while (*fmt) {
979
980 // lwsl_notice("%s: %c %d %d\n", __func__, *fmt, sp, literal);
981
982 if (swallow) {
983 swallow--;
984 fmt++;
985 continue;
986 }
987
988 if (numeric) {
989 if (*fmt >= '0' && *fmt <= '9')
990 fmt++;
991 numeric = 0;
992 if (*fmt != '(')
993 bump("a");
994 }
995
996 if (literal) {
997 if (*fmt == '\\' && fmt[1]) {
998 fmt += 2;
999 continue;
1000 }
1001 if (*fmt == '\'') {
1002 literal = 0;
1003 if (!sp && stack[sp] == '\'')
1004 return count[sp];
1005
1006 if (sp)
1007 sp--;
1008 fmt++;
1009 continue;
1010 }
1011
1012 bump("b");
1013 fmt++;
1014 continue;
1015 }
1016
1017 if (*fmt == '\'') {
1018 bump("c");
1019 sp++;
1020 literal = 1;
1021 fmt++;
1022 continue;
1023 }
1024
1025 switch (pc) {
1026 case 1:
1027 if (*fmt == '.') {
1028 pc++;
1029 fmt++;
1030 continue;
1031 }
1032 if (*fmt == 'l') {
1033 pc++;
1034 fmt++;
1035 continue;
1036 }
1037 /* fallthru */
1038 case 2:
1039 if (*fmt == '*') {
1040 pc++;
1041 fmt++;
1042 continue;
1043 }
1044 if (*fmt == 'l') {
1045 pc++;
1046 fmt++;
1047 continue;
1048 }
1049 /* fallthru */
1050 case 3:
1051 bump("pc");
1052 pc = 0;
1053 fmt++;
1054 continue;
1055 }
1056
1057 switch (*fmt) {
1058
1059 case '<':
1060 swallow = 1;
1061 /* fallthru */
1062 case '[':
1063 case '(':
1064 case '{':
1065 if (sp == sizeof(stack))
1066 return -2;
1067
1068 bump("d");
1069 sp++;
1070 stack[sp] = *fmt;
1071 count[sp] = 0;
1072 break;
1073 case ' ':
1074 break;
1075 case ',':
1076 //count[sp]++;
1077 break;
1078 case ':':
1079 if (stack[sp] != '{')
1080 goto mismatch;
1081 //count[sp]++;
1082 break;
1083 case '%':
1084 pc = 1;
1085 break;
1086 case ']':
1087 if (stack[sp] != '[')
1088 goto mismatch;
1089 goto pop;
1090 case ')':
1091 if (stack[sp] != '(')
1092 goto mismatch;
1093 goto pop;
1094 case '}':
1095 if (stack[sp] != '{')
1096 goto mismatch;
1097 goto pop;
1098 case '>':
1099 if (stack[sp] != '<')
1100 goto mismatch;
1101 pop:
1102 if (sp) {
1103 sp--;
1104 break;
1105 }
1106
1107 if (stack[0] == '{') {
1108 /* args have to come in pairs */
1109 if (count[0] & 1) {
1110 lwsl_err("%s: odd map args %d %s\n",
1111 __func__, count[0], fmt);
1112 return -2;
1113 }
1114 // lwsl_notice("%s: return %d pairs\n", __func__, count[0] >> 1);
1115 /* report how many pairs */
1116 return count[0] >> 1;
1117 }
1118
1119 // lwsl_notice("%s: return %d items\n", __func__, count[0]);
1120
1121 return count[0];
1122
1123 case '0':
1124 case '1':
1125 case '2':
1126 case '3':
1127 case '4':
1128 case '5':
1129 case '6':
1130 case '7':
1131 case '8':
1132 case '9':
1133 numeric = 1;
1134
1135 break;
1136
1137 default:
1138 bump("e");
1139 break;
1140 }
1141 fmt++;
1142 }
1143
1144 return -1;
1145
1146 mismatch:
1147 lwsl_err("%s: format mismatch %c %c\n", __func__, stack[sp], *fmt);
1148
1149 return -2;
1150 }
1151
1152 void
lws_lec_signed(lws_lec_pctx_t * ctx,int64_t num)1153 lws_lec_signed(lws_lec_pctx_t *ctx, int64_t num)
1154 {
1155 if (num < 0)
1156 lws_lec_int(ctx, LWS_CBOR_MAJTYP_INT_NEG, 0,
1157 (uint64_t)(-1ll - num));
1158 else
1159 lws_lec_int(ctx, LWS_CBOR_MAJTYP_UINT, 0, (uint64_t)num);
1160 }
1161
1162 void
lws_lec_int(lws_lec_pctx_t * ctx,uint8_t opcode,uint8_t indet,uint64_t num)1163 lws_lec_int(lws_lec_pctx_t *ctx, uint8_t opcode, uint8_t indet, uint64_t num)
1164 {
1165 uint8_t hint = 0;
1166 unsigned int n;
1167
1168 if (indet) {
1169 ctx->scratch[ctx->scratch_len++] = (uint8_t)(opcode |
1170 LWS_CBOR_INDETERMINITE);
1171 return;
1172 }
1173
1174 if ((opcode & LWS_CBOR_MAJTYP_MASK) == LWS_CBOR_MAJTYP_FLOAT) {
1175 hint = opcode & LWS_CBOR_SUBMASK;
1176 switch (hint) {
1177 case LWS_CBOR_M7_SUBTYP_FLOAT16:
1178 num <<= 48;
1179 break;
1180 case LWS_CBOR_M7_SUBTYP_FLOAT32:
1181 num <<= 32;
1182 break;
1183 }
1184 } else {
1185
1186 if (num < LWS_CBOR_1) {
1187 ctx->scratch[ctx->scratch_len++] = (uint8_t)(opcode | num);
1188 return;
1189 }
1190
1191 if (!(num & (uint64_t)(~0xffull))) {
1192 hint = LWS_CBOR_1;
1193 num <<= 56;
1194 } else
1195 if (!(num & (uint64_t)(~0xffffull))) {
1196 hint = LWS_CBOR_2;
1197 num <<= 48;
1198 } else
1199 if (!(num & (uint64_t)(~0xffffffffull))) {
1200 hint = LWS_CBOR_4;
1201 num <<= 32;
1202 }
1203 else
1204 hint = LWS_CBOR_8;
1205 }
1206
1207 ctx->scratch[ctx->scratch_len++] = (uint8_t)(opcode | hint);
1208 n = 1u << (hint - LWS_CBOR_1);
1209 while (n--) {
1210 ctx->scratch[ctx->scratch_len++] = (uint8_t)(num >> 56);
1211 num <<= 8;
1212 }
1213 }
1214
1215 enum {
1216 NATTYPE_INT,
1217 NATTYPE_LONG,
1218 NATTYPE_LONG_LONG,
1219 NATTYPE_PTR,
1220 NATTYPE_DOUBLE,
1221 };
1222
1223 int
lws_lec_scratch(lws_lec_pctx_t * ctx)1224 lws_lec_scratch(lws_lec_pctx_t *ctx)
1225 {
1226 size_t s;
1227
1228 if (!ctx->scratch_len)
1229 return 0;
1230
1231 s = lws_ptr_diff_size_t(ctx->end, ctx->buf);
1232 if (s > (size_t)ctx->scratch_len)
1233 s = (size_t)ctx->scratch_len;
1234
1235 memcpy(ctx->buf, ctx->scratch, s);
1236 ctx->buf += s;
1237 ctx->scratch_len = (uint8_t)(ctx->scratch_len - (uint8_t)s);
1238
1239 return ctx->buf == ctx->end;
1240 }
1241
1242 enum lws_lec_pctx_ret
lws_lec_vsprintf(lws_lec_pctx_t * ctx,const char * fmt,va_list args)1243 lws_lec_vsprintf(lws_lec_pctx_t *ctx, const char *fmt, va_list args)
1244 {
1245 size_t fl = strlen(fmt);
1246 uint64_t u64;
1247 int64_t i64;
1248 #if defined(LWS_WITH_CBOR_FLOAT)
1249 double dbl;
1250 #endif
1251 size_t s;
1252 char c;
1253 int n;
1254
1255 /*
1256 * We might be being called after the first time, since we had to emit
1257 * output buffer(s) before we could move on in the format string. For
1258 * this case, reposition ourselves at the vaarg we got to from the last
1259 * call.
1260 */
1261
1262 for (n = 0; n < ctx->vaa_pos; n++) {
1263
1264 switch (ctx->vaa[n]) {
1265 case NATTYPE_INT:
1266 (void)va_arg(args, int);
1267 break;
1268 case NATTYPE_LONG:
1269 (void)va_arg(args, long);
1270 break;
1271 case NATTYPE_LONG_LONG:
1272 (void)va_arg(args, long long);
1273 break;
1274 case NATTYPE_PTR:
1275 (void)va_arg(args, const char *);
1276 break;
1277 case NATTYPE_DOUBLE:
1278 (void)va_arg(args, double);
1279 break;
1280 }
1281 if (ctx->state == CBPS_STRING_BODY)
1282 /*
1283 * when copying out text or binary strings, we reload
1284 * the %s or %.*s pointer on subsequent calls, in case
1285 * it was on the stack. The length and contents should
1286 * not change between calls, but it's OK if the source
1287 * address does.
1288 */
1289 ctx->ongoing_src = va_arg(args, uint8_t *);
1290 }
1291
1292 while (ctx->buf != ctx->end) {
1293
1294 /*
1295 * We write small things into the context scratch array, then
1296 * copy that into the output buffer fragmenting as needed. Next
1297 * time we will finish emptying the scratch into the output
1298 * buffer preferentially.
1299 *
1300 * Then we don't otherwise have to handle fragmentations in
1301 * order to exactly fill the output buffer, simplifying
1302 * everything else.
1303 */
1304
1305 if (lws_lec_scratch(ctx))
1306 break;
1307
1308 if (ctx->fmt_pos >= fl) {
1309 if (ctx->state == CBPS_IDLE)
1310 break;
1311 c = 0;
1312 } else
1313 c = fmt[ctx->fmt_pos];
1314
1315 // lwsl_notice("%s: %d %d %c\n", __func__, ctx->state, ctx->sp, c);
1316
1317 switch (ctx->state) {
1318 case CBPS_IDLE:
1319 ctx->scratch_len = 0;
1320 switch (c) {
1321 case '[':
1322 n = format_scan(&fmt[ctx->fmt_pos]);
1323 if (n == -2)
1324 return LWS_LECPCTX_RET_FAIL;
1325 lws_lec_int(ctx, LWS_CBOR_MAJTYP_ARRAY, n == -1,
1326 (uint64_t)n);
1327 goto stack_push;
1328 case '{':
1329 n = format_scan(&fmt[ctx->fmt_pos]);
1330 if (n == -2)
1331 return LWS_LECPCTX_RET_FAIL;
1332 lws_lec_int(ctx, LWS_CBOR_MAJTYP_MAP, n == -1,
1333 (uint64_t)n);
1334 goto stack_push;
1335 case '(':
1336 /* must be preceded by a number */
1337 goto fail;
1338
1339 case '<': /* <t or <b */
1340 ctx->state = CBPS_CONTYPE;
1341 break;
1342
1343 case ']':
1344 if (!ctx->sp || ctx->stack[ctx->sp - 1] != '[')
1345 return LWS_LECPCTX_RET_FAIL;
1346 ctx->sp--;
1347 break;
1348 case '}':
1349 if (!ctx->sp || ctx->stack[ctx->sp - 1] != '{')
1350 return LWS_LECPCTX_RET_FAIL;
1351 ctx->sp--;
1352 break;
1353 case ')':
1354 if (!ctx->sp || ctx->stack[ctx->sp - 1] != '(') {
1355 lwsl_notice("bad tag end %d %c\n",
1356 ctx->sp, ctx->stack[ctx->sp - 1]);
1357 goto fail;
1358 }
1359 ctx->sp--;
1360 break;
1361 case '>':
1362 if (!ctx->sp || ctx->stack[ctx->sp - 1] != '<')
1363 return LWS_LECPCTX_RET_FAIL;
1364 ctx->scratch[ctx->scratch_len++] =
1365 (uint8_t)(LWS_CBOR_MAJTYP_FLOAT |
1366 LWS_CBOR_M7_BREAK);
1367 ctx->sp--;
1368 break;
1369 case '\'':
1370 n = format_scan(&fmt[ctx->fmt_pos]);
1371 // lwsl_notice("%s: quote fs %d\n", __func__, n);
1372 if (n < 0)
1373 return LWS_LECPCTX_RET_FAIL;
1374 lws_lec_int(ctx, LWS_CBOR_MAJTYP_TSTR, 0,
1375 (uint64_t)n);
1376 ctx->state = CBPS_STRING_LIT;
1377 break;
1378 case '%':
1379 if (ctx->vaa_pos >= sizeof(ctx->vaa) - 1) {
1380 lwsl_err("%s: too many %%\n", __func__);
1381 goto fail;
1382 }
1383 ctx->_long = 0;
1384 ctx->dotstar = 0;
1385 ctx->state = CBPS_PC1;
1386 break;
1387 case ':':
1388 break;
1389 case ',':
1390 break;
1391 case '-':
1392 ctx->item.opcode = LWS_CBOR_MAJTYP_INT_NEG;
1393 ctx->item.u.i64 = 0;
1394 ctx->state = CBPS_NUM_LIT;
1395 break;
1396 case '0':
1397 case '1':
1398 case '2':
1399 case '3':
1400 case '4':
1401 case '5':
1402 case '6':
1403 case '7':
1404 case '8':
1405 case '9':
1406 ctx->item.opcode = LWS_CBOR_MAJTYP_UINT;
1407 ctx->item.u.u64 = (uint64_t)(c - '0');
1408 ctx->state = CBPS_NUM_LIT;
1409 break;
1410 }
1411 break;
1412 case CBPS_PC1:
1413 if (c == 'l') {
1414 ctx->_long++;
1415 ctx->state = CBPS_PC2;
1416 break;
1417 }
1418 if (c == '.') {
1419 ctx->dotstar++;
1420 ctx->state = CBPS_PC2;
1421 break;
1422 }
1423 /* fallthru */
1424
1425 case CBPS_PC2:
1426 if (c == 'l') {
1427 ctx->_long++;
1428 ctx->state = CBPS_PC3;
1429 break;
1430 }
1431 if (c == '*') {
1432 ctx->dotstar++;
1433 ctx->state = CBPS_PC3;
1434 break;
1435 }
1436 /* fallthru */
1437
1438 case CBPS_PC3:
1439 switch (c) {
1440 case 'd':
1441 switch (ctx->_long) {
1442 case 0:
1443 i64 = (int64_t)va_arg(args, int);
1444 ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT;
1445 break;
1446 case 1:
1447 i64 = (int64_t)va_arg(args, long);
1448 ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG;
1449 break;
1450 case 2:
1451 i64 = (int64_t)va_arg(args, long long);
1452 ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG_LONG;
1453 break;
1454 }
1455 if (i64 < 0)
1456 lws_lec_int(ctx,
1457 LWS_CBOR_MAJTYP_INT_NEG, 0,
1458 (uint64_t)(-1ll - i64));
1459 else
1460 lws_lec_int(ctx,
1461 LWS_CBOR_MAJTYP_UINT, 0,
1462 (uint64_t)i64);
1463 break;
1464 case 'u':
1465 switch (ctx->_long) {
1466 case 0:
1467 u64 = (uint64_t)va_arg(args, unsigned int);
1468 ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT;
1469 break;
1470 case 1:
1471 u64 = (uint64_t)va_arg(args, unsigned long);
1472 ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG;
1473 break;
1474 case 2:
1475 u64 = (uint64_t)va_arg(args, unsigned long long);
1476 ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG_LONG;
1477 break;
1478 }
1479 lws_lec_int(ctx, LWS_CBOR_MAJTYP_UINT, 0, u64);
1480 break;
1481 case 's': /* text string */
1482 ctx->ongoing_done = 0;
1483 if (ctx->dotstar == 2) {
1484 ctx->ongoing_len = (uint64_t)va_arg(args, int);
1485 ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT;
1486 }
1487 /* vaa for ptr done at end of body copy */
1488 ctx->ongoing_src = va_arg(args, uint8_t *);
1489 if (ctx->dotstar != 2)
1490 ctx->ongoing_len = (uint64_t)strlen(
1491 (const char *)ctx->ongoing_src);
1492 lws_lec_int(ctx, LWS_CBOR_MAJTYP_TSTR, 0, ctx->ongoing_len);
1493 ctx->state = CBPS_STRING_BODY;
1494 ctx->fmt_pos++;
1495 continue;
1496 case 'b': /* binary string (%.*b only) */
1497 if (ctx->dotstar != 2)
1498 goto fail;
1499 ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT;
1500 ctx->ongoing_done = 0;
1501 ctx->ongoing_len = (uint64_t)va_arg(args, int);
1502 /* vaa for ptr done at end of body copy */
1503 ctx->ongoing_src = va_arg(args, uint8_t *);
1504 lws_lec_int(ctx, LWS_CBOR_MAJTYP_BSTR, 0, ctx->ongoing_len);
1505 ctx->state = CBPS_STRING_BODY;
1506 ctx->fmt_pos++;
1507 continue;
1508 case 't': /* dynamic tag */
1509 switch (ctx->_long) {
1510 case 0:
1511 ctx->item.u.u64 = (uint64_t)va_arg(args, int);
1512 ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT;
1513 break;
1514 case 1:
1515 ctx->item.u.u64 = (uint64_t)va_arg(args, long);
1516 ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG;
1517 break;
1518 case 2:
1519 ctx->item.u.u64 = (uint64_t)va_arg(args, long long);
1520 ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG_LONG;
1521 break;
1522 }
1523 ctx->item.opcode = LWS_CBOR_MAJTYP_UINT;
1524 ctx->fmt_pos++;
1525 if (ctx->fmt_pos >= fl)
1526 continue;
1527 c = fmt[ctx->fmt_pos];
1528 if (c != '(')
1529 goto fail;
1530 goto tag_body;
1531 #if defined(LWS_WITH_CBOR_FLOAT)
1532 case 'f': /* floating point double */
1533 dbl = va_arg(args, double);
1534
1535 if (dbl == (float)dbl) {
1536 uint16_t hf;
1537 union {
1538 uint32_t ui;
1539 float f;
1540 } u1, u2;
1541
1542 u1.f = (float)dbl;
1543 lws_singles2halfp(&hf, u1.ui);
1544 lws_halfp2singles(&u2.ui, hf);
1545
1546 if ((isinf(u1.f) && isinf(u2.f)) ||
1547 (isnan(u1.f) && isnan(u2.f)) ||
1548 u1.f == u2.f) {
1549 lws_lec_int(ctx,
1550 LWS_CBOR_MAJTYP_FLOAT |
1551 LWS_CBOR_M7_SUBTYP_FLOAT16,
1552 0, hf);
1553 break;
1554 }
1555 /* do it as 32-bit float */
1556 lws_lec_int(ctx,
1557 LWS_CBOR_MAJTYP_FLOAT |
1558 LWS_CBOR_M7_SUBTYP_FLOAT32,
1559 0, u1.ui);
1560 break;
1561 }
1562
1563 /* do it as 64-bit double */
1564
1565 {
1566 union {
1567 uint64_t ui;
1568 double f;
1569 } u3;
1570
1571 u3.f = dbl;
1572 lws_lec_int(ctx,
1573 LWS_CBOR_MAJTYP_FLOAT |
1574 LWS_CBOR_M7_SUBTYP_FLOAT64,
1575 0, u3.ui);
1576 }
1577 break;
1578 #else
1579 case 'f':
1580 lwsl_err("%s: no FP support\n", __func__);
1581 goto fail;
1582 #endif
1583 }
1584 ctx->state = CBPS_IDLE;
1585 break;
1586
1587 case CBPS_STRING_BODY:
1588 s = lws_ptr_diff_size_t(ctx->end, ctx->buf);
1589 if (s > (size_t)(ctx->ongoing_len - ctx->ongoing_done))
1590 s = (size_t)(ctx->ongoing_len - ctx->ongoing_done);
1591 memcpy(ctx->buf, ctx->ongoing_src + ctx->ongoing_done, s);
1592 ctx->buf += s;
1593 ctx->ongoing_done += s;
1594 if (ctx->ongoing_len == ctx->ongoing_done) {
1595 /* vaa for ptr */
1596 ctx->vaa[ctx->vaa_pos++] = NATTYPE_PTR;
1597 ctx->state = CBPS_IDLE;
1598 }
1599 continue;
1600
1601 case CBPS_NUM_LIT:
1602 if (c >= '0' && c <= '9') {
1603 ctx->item.u.u64 = (ctx->item.u.u64 * 10) +
1604 (uint64_t)(c - '0');
1605 break;
1606 }
1607
1608 if (ctx->item.opcode == LWS_CBOR_MAJTYP_INT_NEG)
1609 ctx->item.u.i64--;
1610
1611 if (c == '(') { /* tag qualifier */
1612 tag_body:
1613 n = format_scan(&fmt[ctx->fmt_pos]);
1614 if (n == -2)
1615 goto fail;
1616 /*
1617 * inteterminite length not possible for tag,
1618 * take it to mean that the closure is in a
1619 * later format string
1620 */
1621
1622 lws_lec_int(ctx, LWS_CBOR_MAJTYP_TAG, 0,
1623 ctx->item.u.u64);
1624
1625 stack_push:
1626 if (ctx->sp >= sizeof(ctx->stack))
1627 return LWS_LECPCTX_RET_FAIL;
1628 ctx->stack[ctx->sp] = (uint8_t)c;
1629 ctx->indet[ctx->sp++] = (uint8_t)(n == -1);
1630 // lwsl_notice("%s: pushed %c\n", __func__, c);
1631 ctx->state = CBPS_IDLE;
1632 break;
1633 }
1634
1635 lws_lec_int(ctx, ctx->item.opcode, 0, ctx->item.u.u64);
1636
1637 ctx->state = CBPS_IDLE;
1638 /* deal with the terminating char fresh */
1639 continue;
1640
1641 case CBPS_STRING_LIT:
1642 if (!ctx->escflag && c == '\\') {
1643 ctx->escflag = 1;
1644 break;
1645 }
1646 if (!ctx->escflag && c == '\'') {
1647 ctx->state = CBPS_IDLE;
1648 break;
1649 }
1650
1651 *ctx->buf++ = (uint8_t)c;
1652 ctx->escflag = 0;
1653
1654 break;
1655
1656 case CBPS_CONTYPE:
1657 if (c != 't' && c != 'b')
1658 return LWS_LECPCTX_RET_FAIL;
1659
1660 lws_lec_int(ctx, c == 't' ? LWS_CBOR_MAJTYP_TSTR :
1661 LWS_CBOR_MAJTYP_BSTR, 1, 0);
1662 c = '<';
1663 n = 0;
1664 goto stack_push;
1665 }
1666
1667 ctx->fmt_pos++;
1668 }
1669
1670 ctx->used = lws_ptr_diff_size_t(ctx->buf, ctx->start);
1671 // lwsl_notice("%s: ctx->used %d\n", __func__, (int)ctx->used);
1672
1673 if (ctx->buf == ctx->end || ctx->scratch_len)
1674 return LWS_LECPCTX_RET_AGAIN;
1675
1676 ctx->fmt_pos = 0;
1677 ctx->vaa_pos = 0;
1678
1679 return LWS_LECPCTX_RET_FINISHED;
1680
1681 fail:
1682 lwsl_notice("%s: failed\n", __func__);
1683
1684 ctx->fmt_pos = 0;
1685
1686 return LWS_LECPCTX_RET_FAIL;
1687 }
1688