1 /*
2 * Copyright (c) 1999-2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * HISTORY
31 *
32 * OSUnserializeXML.y created by rsulack on Tue Oct 12 1999
33 */
34
35 // parser for unserializing OSContainer objects serialized to XML
36 //
37 // to build :
38 // bison -p OSUnserializeXML OSUnserializeXML.y
39 // head -50 OSUnserializeXML.y > ../libkern/c++/OSUnserializeXMLSharedImplementation.h
40 // sed -e "s/#include <stdio.h>//" < OSUnserializeXML.tab.c >> ../libkern/c++/OSUnserializeXMLSharedImplementation.h
41 //
42 // when changing code check in both OSUnserializeXML.y and OSUnserializeXMLSharedImplementation.h
43 //
44 //
45 //
46 //
47 //
48 // DO NOT EDIT OSUnserializeXMLSharedImplementation.h!
49 //
50 // this means you!
51 //
52 //
53 //
54 //
55 //
56 //
57
58
59 %pure_parser
60
61 %{
62 #include <string.h>
63 #if KERNEL
64 #include <libkern/c++/OSMetaClass.h>
65 #include <libkern/c++/OSContainers.h>
66 #include <libkern/c++/OSLib.h>
67 #else /* !KERNEL */
68 #include <DriverKit/DriverKit.h>
69 #endif /* KERNEL */
70
71
72 #define MAX_OBJECTS 131071
73 #define MAX_REFED_OBJECTS 65535
74
75 #define YYSTYPE object_t *
76 #define YYPARSE_PARAM state
77 #define YYLEX_PARAM (parser_state_t *)state
78
79 // this is the internal struct used to hold objects on parser stack
80 // it represents objects both before and after they have been created
81 typedef struct object {
82 struct object *next;
83 struct object *free;
84 struct object *elements;
85 OSObject *object;
86 OSSymbol *key; // for dictionary
87 int size;
88 void *data; // for data
89 char *string; // for string & symbol
90 int string_alloc_length;
91 long long number; // for number
92 int idref;
93 } object_t;
94
95 // this code is reentrant, this structure contains all
96 // state information for the parsing of a single buffer
97 typedef struct parser_state {
98 const char *parseBuffer; // start of text to be parsed
99 int parseBufferIndex; // current index into text
100 int lineNumber; // current line number
101 object_t *objects; // internal objects in use
102 object_t *freeObjects; // internal objects that are free
103 OSDictionary *tags; // used to remember "ID" tags
104 OSString **errorString; // parse error with line
105 OSObject *parsedObject; // resultant object of parsed text
106 int parsedObjectCount;
107 int retrievedObjectCount;
108 } parser_state_t;
109
110 #define STATE ((parser_state_t *)state)
111
112 #undef yyerror
113 #define yyerror(s) OSUnserializeerror(STATE, (s))
114 static int OSUnserializeerror(parser_state_t *state, const char *s);
115
116 static int yylex(YYSTYPE *lvalp, parser_state_t *state);
117
118 static object_t *newObject(parser_state_t *state);
119 static void freeObject(parser_state_t *state, object_t *o);
120 static void rememberObject(parser_state_t *state, int tag, OSObject *o);
121 static object_t *retrieveObject(parser_state_t *state, int tag);
122 static void cleanupObjects(parser_state_t *state);
123
124 static object_t *buildDictionary(parser_state_t *state, object_t *o);
125 static object_t *buildArray(parser_state_t *state, object_t *o);
126 static object_t *buildSet(parser_state_t *state, object_t *o);
127 static object_t *buildString(parser_state_t *state, object_t *o);
128 static object_t *buildSymbol(parser_state_t *state, object_t *o);
129 static object_t *buildData(parser_state_t *state, object_t *o);
130 static object_t *buildNumber(parser_state_t *state, object_t *o);
131 static object_t *buildBoolean(parser_state_t *state, object_t *o);
132
133 #if KERNEL
134 __BEGIN_DECLS
135 #include <kern/kalloc.h>
136 __END_DECLS
137
138 #define malloc(size) malloc_impl(size)
139 #define malloc_type(type) kalloc_type(type, Z_SET_NOTSHARED)
140 static inline void *
malloc_impl(size_t size)141 malloc_impl(size_t size)
142 {
143 if (size == 0) {
144 return NULL;
145 }
146 return kalloc_data(size,
147 Z_VM_TAG_BT(Z_WAITOK_ZERO, VM_KERN_MEMORY_LIBKERN));
148 }
149
150 #define free(addr) free_impl(addr)
151 #define free_type(type, addr) kfree_type(type, addr)
152 static inline void
free_impl(void * addr)153 free_impl(void *addr)
154 {
155 kfree_data_addr(addr);
156 }
157 static inline void
safe_free(void * addr,size_t size)158 safe_free(void *addr, size_t size)
159 {
160 kfree_data(addr, size);
161 }
162
163 #define realloc(addr, osize, nsize) realloc_impl(addr, osize, nsize)
164 static inline void *
realloc_impl(void * addr,size_t osize,size_t nsize)165 realloc_impl(void *addr, size_t osize, size_t nsize)
166 {
167 return krealloc_data(addr, osize, nsize,
168 Z_VM_TAG_BT(Z_WAITOK_ZERO, VM_KERN_MEMORY_LIBKERN));
169 }
170 #else /* !KERNEL */
171 #define malloc(size) malloc_impl(size)
172 #define malloc_type(type) (type *) calloc(1, sizeof(type))
173 static inline void *
malloc_impl(size_t size)174 malloc_impl(size_t size)
175 {
176 if (size == 0) {
177 return NULL;
178 }
179 return calloc(1, size);
180 }
181 #define safe_free(addr, size) free(addr)
182 #define free_type(type, addr) safe_free(addr, sizeof(type))
183 #define realloc(addr, osize, nsize) realloc_impl(addr, osize, nsize)
184 static inline void *
realloc_impl(void * addr,size_t osize,size_t nsize)185 realloc_impl(void *addr, size_t osize, size_t nsize)
186 {
187 void * nmem;
188
189 if (!addr) {
190 return malloc(nsize);
191 }
192 if (nsize == osize) {
193 return addr;
194 }
195 nmem = (realloc)(addr, nsize);
196 if (nmem && nsize > osize) {
197 bzero((uint8_t *)nmem + osize, nsize - osize);
198 }
199
200 return nmem;
201 }
202 #endif /* KERNEL */
203
204 %}
205 %token ARRAY
206 %token BOOLEAN
207 %token DATA
208 %token DICTIONARY
209 %token IDREF
210 %token KEY
211 %token NUMBER
212 %token SET
213 %token STRING
214 %token SYNTAX_ERROR
215 %% /* Grammar rules and actions follow */
216
217 input: /* empty */ { yyerror("unexpected end of buffer");
218 YYERROR;
219 }
220 | object { STATE->parsedObject = $1->object;
221 $1->object = 0;
222 freeObject(STATE, $1);
223 YYACCEPT;
224 }
225 | SYNTAX_ERROR { yyerror("syntax error");
226 YYERROR;
227 }
228 ;
229
230 object: dict { $$ = buildDictionary(STATE, $1);
231
232 if (!yyval->object) {
233 yyerror("buildDictionary");
234 YYERROR;
235 }
236 STATE->parsedObjectCount++;
237 if (STATE->parsedObjectCount > MAX_OBJECTS) {
238 yyerror("maximum object count");
239 YYERROR;
240 }
241 }
242 | array { $$ = buildArray(STATE, $1);
243
244 if (!yyval->object) {
245 yyerror("buildArray");
246 YYERROR;
247 }
248 STATE->parsedObjectCount++;
249 if (STATE->parsedObjectCount > MAX_OBJECTS) {
250 yyerror("maximum object count");
251 YYERROR;
252 }
253 }
254 | set { $$ = buildSet(STATE, $1);
255
256 if (!yyval->object) {
257 yyerror("buildSet");
258 YYERROR;
259 }
260 STATE->parsedObjectCount++;
261 if (STATE->parsedObjectCount > MAX_OBJECTS) {
262 yyerror("maximum object count");
263 YYERROR;
264 }
265 }
266 | string { $$ = buildString(STATE, $1);
267
268 if (!yyval->object) {
269 yyerror("buildString");
270 YYERROR;
271 }
272 STATE->parsedObjectCount++;
273 if (STATE->parsedObjectCount > MAX_OBJECTS) {
274 yyerror("maximum object count");
275 YYERROR;
276 }
277 }
278 | data { $$ = buildData(STATE, $1);
279
280 if (!yyval->object) {
281 yyerror("buildData");
282 YYERROR;
283 }
284 STATE->parsedObjectCount++;
285 if (STATE->parsedObjectCount > MAX_OBJECTS) {
286 yyerror("maximum object count");
287 YYERROR;
288 }
289 }
290 | number { $$ = buildNumber(STATE, $1);
291
292 if (!yyval->object) {
293 yyerror("buildNumber");
294 YYERROR;
295 }
296 STATE->parsedObjectCount++;
297 if (STATE->parsedObjectCount > MAX_OBJECTS) {
298 yyerror("maximum object count");
299 YYERROR;
300 }
301 }
302 | boolean { $$ = buildBoolean(STATE, $1);
303
304 if (!yyval->object) {
305 yyerror("buildBoolean");
306 YYERROR;
307 }
308 STATE->parsedObjectCount++;
309 if (STATE->parsedObjectCount > MAX_OBJECTS) {
310 yyerror("maximum object count");
311 YYERROR;
312 }
313 }
314 | idref { $$ = retrieveObject(STATE, $1->idref);
315 if ($$) {
316 STATE->retrievedObjectCount++;
317 $$->object->retain();
318 if (STATE->retrievedObjectCount > MAX_REFED_OBJECTS) {
319 yyerror("maximum object reference count");
320 YYERROR;
321 }
322 } else {
323 yyerror("forward reference detected");
324 YYERROR;
325 }
326 freeObject(STATE, $1);
327
328 STATE->parsedObjectCount++;
329 if (STATE->parsedObjectCount > MAX_OBJECTS) {
330 yyerror("maximum object count");
331 YYERROR;
332 }
333 }
334 ;
335
336 //------------------------------------------------------------------------------
337
338 dict: '{' '}' { $$ = $1;
339 $$->elements = NULL;
340 }
341 | '{' pairs '}' { $$ = $1;
342 $$->elements = $2;
343 }
344 | DICTIONARY
345 ;
346
347 pairs: pair
348 | pairs pair { $$ = $2;
349 $$->next = $1;
350
351 object_t *o;
352 o = $$->next;
353 while (o) {
354 if (o->key == $$->key) {
355 yyerror("duplicate dictionary key");
356 YYERROR;
357 }
358 o = o->next;
359 }
360 }
361 ;
362
363 pair: key object { $$ = $1;
364 $$->key = (OSSymbol *)$$->object;
365 $$->object = $2->object;
366 $$->next = NULL;
367 $2->object = 0;
368 freeObject(STATE, $2);
369 }
370 ;
371
372 key: KEY { $$ = buildSymbol(STATE, $1);
373
374 // STATE->parsedObjectCount++;
375 // if (STATE->parsedObjectCount > MAX_OBJECTS) {
376 // yyerror("maximum object count");
377 // YYERROR;
378 // }
379 }
380 ;
381
382 //------------------------------------------------------------------------------
383
384 array: '(' ')' { $$ = $1;
385 $$->elements = NULL;
386 }
387 | '(' elements ')' { $$ = $1;
388 $$->elements = $2;
389 }
390 | ARRAY
391 ;
392
393 set: '[' ']' { $$ = $1;
394 $$->elements = NULL;
395 }
396 | '[' elements ']' { $$ = $1;
397 $$->elements = $2;
398 }
399 | SET
400 ;
401
402 elements: object { $$ = $1;
403 $$->next = NULL;
404 }
405 | elements object { $$ = $2;
406 $$->next = $1;
407 }
408 ;
409
410 //------------------------------------------------------------------------------
411
412 boolean: BOOLEAN
413 ;
414
415 data: DATA
416 ;
417
418 idref: IDREF
419 ;
420
421 number: NUMBER
422 ;
423
424 string: STRING
425 ;
426
427 %%
428
429 int
430 OSUnserializeerror(parser_state_t * state, const char *s) /* Called by yyparse on errors */
431 {
432 if (state->errorString) {
433 char tempString[128];
434 snprintf(tempString, 128, "OSUnserializeXML: %s near line %d\n", s, state->lineNumber);
435 *(state->errorString) = OSString::withCString(tempString);
436 }
437
438 return 0;
439 }
440
441 #define TAG_MAX_LENGTH 32
442 #define TAG_MAX_ATTRIBUTES 32
443 #define TAG_BAD 0
444 #define TAG_START 1
445 #define TAG_END 2
446 #define TAG_EMPTY 3
447 #define TAG_IGNORE 4
448
449 #define currentChar() (state->parseBuffer[state->parseBufferIndex])
450 #define nextChar() (state->parseBuffer[++state->parseBufferIndex])
451 #define prevChar() (state->parseBuffer[state->parseBufferIndex - 1])
452
453 #define isSpace(c) ((c) == ' ' || (c) == '\t')
454 #define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
455 #define isDigit(c) ((c) >= '0' && (c) <= '9')
456 #define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f')
457 #define isHexDigit(c) (isDigit(c) || isAlphaDigit(c))
458 #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-'))
459
460 static int
getTag(parser_state_t * state,char tag[TAG_MAX_LENGTH],int * attributeCount,char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH])461 getTag(parser_state_t *state,
462 char tag[TAG_MAX_LENGTH],
463 int *attributeCount,
464 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],
465 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] )
466 {
467 int length = 0;
468 int c = currentChar();
469 int tagType = TAG_START;
470
471 *attributeCount = 0;
472
473 if (c != '<') {
474 return TAG_BAD;
475 }
476 c = nextChar(); // skip '<'
477
478
479 // <!TAG declarations >
480 // <!-- comments -->
481 if (c == '!') {
482 c = nextChar();
483 bool isComment = (c == '-') && ((c = nextChar()) != 0) && (c == '-');
484 if (!isComment && !isAlpha(c)) {
485 return TAG_BAD; // <!1, <!-A, <!eos
486 }
487 while (c && (c = nextChar()) != 0) {
488 if (c == '\n') {
489 state->lineNumber++;
490 }
491 if (isComment) {
492 if (c != '-') {
493 continue;
494 }
495 c = nextChar();
496 if (c != '-') {
497 continue;
498 }
499 c = nextChar();
500 }
501 if (c == '>') {
502 (void)nextChar();
503 return TAG_IGNORE;
504 }
505 if (isComment) {
506 break;
507 }
508 }
509 return TAG_BAD;
510 } else
511 // <? Processing Instructions ?>
512 if (c == '?') {
513 while ((c = nextChar()) != 0) {
514 if (c == '\n') {
515 state->lineNumber++;
516 }
517 if (c != '?') {
518 continue;
519 }
520 c = nextChar();
521 if (!c) {
522 return TAG_IGNORE;
523 }
524 if (c == '>') {
525 (void)nextChar();
526 return TAG_IGNORE;
527 }
528 }
529 return TAG_BAD;
530 } else
531 // </ end tag >
532 if (c == '/') {
533 c = nextChar(); // skip '/'
534 tagType = TAG_END;
535 }
536 if (!isAlpha(c)) {
537 return TAG_BAD;
538 }
539
540 /* find end of tag while copying it */
541 while (isAlphaNumeric(c)) {
542 tag[length++] = c;
543 c = nextChar();
544 if (length >= (TAG_MAX_LENGTH - 1)) {
545 return TAG_BAD;
546 }
547 }
548
549 tag[length] = 0;
550
551 // printf("tag %s, type %d\n", tag, tagType);
552
553 // look for attributes of the form attribute = "value" ...
554 while ((c != '>') && (c != '/')) {
555 while (isSpace(c)) {
556 c = nextChar();
557 }
558
559 length = 0;
560 while (isAlphaNumeric(c)) {
561 attributes[*attributeCount][length++] = c;
562 if (length >= (TAG_MAX_LENGTH - 1)) {
563 return TAG_BAD;
564 }
565 c = nextChar();
566 }
567 attributes[*attributeCount][length] = 0;
568
569 while (isSpace(c)) {
570 c = nextChar();
571 }
572
573 if (c != '=') {
574 return TAG_BAD;
575 }
576 c = nextChar();
577
578 while (isSpace(c)) {
579 c = nextChar();
580 }
581
582 if (c != '"') {
583 return TAG_BAD;
584 }
585 c = nextChar();
586 length = 0;
587 while (c != '"') {
588 values[*attributeCount][length++] = c;
589 if (length >= (TAG_MAX_LENGTH - 1)) {
590 return TAG_BAD;
591 }
592 c = nextChar();
593 if (!c) {
594 return TAG_BAD;
595 }
596 }
597 values[*attributeCount][length] = 0;
598
599 c = nextChar(); // skip closing quote
600
601 // printf(" attribute '%s' = '%s', nextchar = '%c'\n",
602 // attributes[*attributeCount], values[*attributeCount], c);
603
604 (*attributeCount)++;
605 if (*attributeCount >= TAG_MAX_ATTRIBUTES) {
606 return TAG_BAD;
607 }
608 }
609
610 if (c == '/') {
611 c = nextChar(); // skip '/'
612 tagType = TAG_EMPTY;
613 }
614 if (c != '>') {
615 return TAG_BAD;
616 }
617 c = nextChar(); // skip '>'
618
619 return tagType;
620 }
621
622 static char *
getString(parser_state_t * state,int * alloc_lengthp)623 getString(parser_state_t *state, int *alloc_lengthp)
624 {
625 int c = currentChar();
626 int start, length, i, j;
627 char * tempString;
628
629 start = state->parseBufferIndex;
630 /* find end of string */
631
632 while (c != 0) {
633 if (c == '\n') {
634 state->lineNumber++;
635 }
636 if (c == '<') {
637 break;
638 }
639 c = nextChar();
640 }
641
642 if (c != '<') {
643 return 0;
644 }
645
646 length = state->parseBufferIndex - start;
647
648 /* copy to null terminated buffer */
649 tempString = (char *)malloc(length + 1);
650 if (tempString == NULL) {
651 printf("OSUnserializeXML: can't alloc temp memory\n");
652 goto error;
653 }
654 if (alloc_lengthp) {
655 *alloc_lengthp = length + 1;
656 }
657
658 // copy out string in tempString
659 // "&" -> '&', "<" -> '<', ">" -> '>'
660
661 i = j = 0;
662 while (i < length) {
663 c = state->parseBuffer[start + i++];
664 if (c != '&') {
665 tempString[j++] = c;
666 } else {
667 if ((i + 3) > length) {
668 goto error;
669 }
670 c = state->parseBuffer[start + i++];
671 if (c == 'l') {
672 if (state->parseBuffer[start + i++] != 't') {
673 goto error;
674 }
675 if (state->parseBuffer[start + i++] != ';') {
676 goto error;
677 }
678 tempString[j++] = '<';
679 continue;
680 }
681 if (c == 'g') {
682 if (state->parseBuffer[start + i++] != 't') {
683 goto error;
684 }
685 if (state->parseBuffer[start + i++] != ';') {
686 goto error;
687 }
688 tempString[j++] = '>';
689 continue;
690 }
691 if ((i + 3) > length) {
692 goto error;
693 }
694 if (c == 'a') {
695 if (state->parseBuffer[start + i++] != 'm') {
696 goto error;
697 }
698 if (state->parseBuffer[start + i++] != 'p') {
699 goto error;
700 }
701 if (state->parseBuffer[start + i++] != ';') {
702 goto error;
703 }
704 tempString[j++] = '&';
705 continue;
706 }
707 goto error;
708 }
709 }
710 tempString[j] = 0;
711
712 // printf("string %s\n", tempString);
713
714 return tempString;
715
716 error:
717 if (tempString) {
718 safe_free(tempString, length + 1);
719 if (alloc_lengthp) {
720 *alloc_lengthp = 0;
721 }
722 }
723 return 0;
724 }
725
726 static long long
getNumber(parser_state_t * state)727 getNumber(parser_state_t *state)
728 {
729 unsigned long long n = 0;
730 int base = 10;
731 bool negate = false;
732 int c = currentChar();
733
734 if (c == '0') {
735 c = nextChar();
736 if (c == 'x') {
737 base = 16;
738 c = nextChar();
739 }
740 }
741 if (base == 10) {
742 if (c == '-') {
743 negate = true;
744 c = nextChar();
745 }
746 while (isDigit(c)) {
747 n = (n * base + c - '0');
748 c = nextChar();
749 }
750 if (negate) {
751 n = (unsigned long long)((long long)n * (long long)-1);
752 }
753 } else {
754 while (isHexDigit(c)) {
755 if (isDigit(c)) {
756 n = (n * base + c - '0');
757 } else {
758 n = (n * base + 0xa + c - 'a');
759 }
760 c = nextChar();
761 }
762 }
763 // printf("number 0x%x\n", (unsigned long)n);
764 return n;
765 }
766
767 // taken from CFXMLParsing/CFPropertyList.c
768
769 static const signed char __CFPLDataDecodeTable[128] = {
770 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
771 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
772 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
773 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
774 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
775 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
776 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
777 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
778 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
779 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
780 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
781 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
782 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
783 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
784 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
785 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
786 };
787
788 #define DATA_ALLOC_SIZE 4096
789
790 static void *
getCFEncodedData(parser_state_t * state,unsigned int * size)791 getCFEncodedData(parser_state_t *state, unsigned int *size)
792 {
793 int numeq = 0, cntr = 0;
794 unsigned int acc = 0;
795 int tmpbufpos = 0;
796 size_t tmpbuflen = DATA_ALLOC_SIZE;
797 unsigned char *tmpbuf = (unsigned char *)malloc(tmpbuflen);
798
799 int c = currentChar();
800 *size = 0;
801
802 while (c != '<') {
803 c &= 0x7f;
804 if (c == 0) {
805 safe_free(tmpbuf, tmpbuflen);
806 return 0;
807 }
808 if (c == '=') {
809 numeq++;
810 } else {
811 numeq = 0;
812 }
813 if (c == '\n') {
814 state->lineNumber++;
815 }
816 if (__CFPLDataDecodeTable[c] < 0) {
817 c = nextChar();
818 continue;
819 }
820 cntr++;
821 acc <<= 6;
822 acc += __CFPLDataDecodeTable[c];
823 if (0 == (cntr & 0x3)) {
824 if (tmpbuflen <= tmpbufpos + 2) {
825 size_t oldsize = tmpbuflen;
826 tmpbuflen *= 2;
827 tmpbuf = (unsigned char *)realloc(tmpbuf, oldsize, tmpbuflen);
828 }
829 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
830 if (numeq < 2) {
831 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
832 }
833 if (numeq < 1) {
834 tmpbuf[tmpbufpos++] = acc & 0xff;
835 }
836 }
837 c = nextChar();
838 }
839 *size = tmpbufpos;
840 if (*size == 0) {
841 safe_free(tmpbuf, tmpbuflen);
842 return 0;
843 }
844 return tmpbuf;
845 }
846
847 static void *
getHexData(parser_state_t * state,unsigned int * size)848 getHexData(parser_state_t *state, unsigned int *size)
849 {
850 int c;
851 unsigned char *d, *start;
852
853 size_t buflen = DATA_ALLOC_SIZE; // initial buffer size
854 start = d = (unsigned char *)malloc(buflen);
855 c = currentChar();
856
857 while (c != '<') {
858 if (isSpace(c)) {
859 while ((c = nextChar()) != 0 && isSpace(c)) {
860 }
861 }
862 ;
863 if (c == '\n') {
864 state->lineNumber++;
865 c = nextChar();
866 continue;
867 }
868
869 // get high nibble
870 if (isDigit(c)) {
871 *d = (c - '0') << 4;
872 } else if (isAlphaDigit(c)) {
873 *d = (0xa + (c - 'a')) << 4;
874 } else {
875 goto error;
876 }
877
878 // get low nibble
879 c = nextChar();
880 if (isDigit(c)) {
881 *d |= c - '0';
882 } else if (isAlphaDigit(c)) {
883 *d |= 0xa + (c - 'a');
884 } else {
885 goto error;
886 }
887
888 d++;
889 size_t oldsize = d - start;
890 if (oldsize >= buflen) {
891 assert(oldsize == buflen);
892 buflen *= 2;
893 start = (unsigned char *)realloc(start, oldsize, buflen);
894 d = start + oldsize;
895 }
896 c = nextChar();
897 }
898
899 *size = d - start;
900 return start;
901
902 error:
903
904 *size = 0;
905 safe_free(start, buflen);
906 return 0;
907 }
908
909 static int
yylex(YYSTYPE * lvalp,parser_state_t * state)910 yylex(YYSTYPE *lvalp, parser_state_t *state)
911 {
912 int c, i;
913 int tagType;
914 char tag[TAG_MAX_LENGTH];
915 int attributeCount;
916 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
917 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
918 object_t *object;
919 int alloc_length;
920 top:
921 c = currentChar();
922
923 /* skip white space */
924 if (isSpace(c)) {
925 while ((c = nextChar()) != 0 && isSpace(c)) {
926 }
927 }
928 ;
929
930 /* keep track of line number, don't return \n's */
931 if (c == '\n') {
932 STATE->lineNumber++;
933 (void)nextChar();
934 goto top;
935 }
936
937 // end of the buffer?
938 if (!c) {
939 return 0;
940 }
941
942 tagType = getTag(STATE, tag, &attributeCount, attributes, values);
943 if (tagType == TAG_BAD) {
944 return SYNTAX_ERROR;
945 }
946 if (tagType == TAG_IGNORE) {
947 goto top;
948 }
949
950 // handle allocation and check for "ID" and "IDREF" tags up front
951 *lvalp = object = newObject(STATE);
952 object->idref = -1;
953 for (i = 0; i < attributeCount; i++) {
954 if (attributes[i][0] == 'I' && attributes[i][1] == 'D') {
955 // check for idref's, note: we ignore the tag, for
956 // this to work correctly, all idrefs must be unique
957 // across the whole serialization
958 if (attributes[i][2] == 'R' && attributes[i][3] == 'E' &&
959 attributes[i][4] == 'F' && !attributes[i][5]) {
960 if (tagType != TAG_EMPTY) {
961 return SYNTAX_ERROR;
962 }
963 object->idref = strtol(values[i], NULL, 0);
964 return IDREF;
965 }
966 // check for id's
967 if (!attributes[i][2]) {
968 object->idref = strtol(values[i], NULL, 0);
969 } else {
970 return SYNTAX_ERROR;
971 }
972 }
973 }
974
975 switch (*tag) {
976 case 'a':
977 if (!strcmp(tag, "array")) {
978 if (tagType == TAG_EMPTY) {
979 object->elements = NULL;
980 return ARRAY;
981 }
982 return (tagType == TAG_START) ? '(' : ')';
983 }
984 break;
985 case 'd':
986 if (!strcmp(tag, "dict")) {
987 if (tagType == TAG_EMPTY) {
988 object->elements = NULL;
989 return DICTIONARY;
990 }
991 return (tagType == TAG_START) ? '{' : '}';
992 }
993 if (!strcmp(tag, "data")) {
994 unsigned int size;
995 if (tagType == TAG_EMPTY) {
996 object->data = NULL;
997 object->size = 0;
998 return DATA;
999 }
1000
1001 bool isHexFormat = false;
1002 for (i = 0; i < attributeCount; i++) {
1003 if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) {
1004 isHexFormat = true;
1005 break;
1006 }
1007 }
1008 // CF encoded is the default form
1009 if (isHexFormat) {
1010 object->data = getHexData(STATE, &size);
1011 } else {
1012 object->data = getCFEncodedData(STATE, &size);
1013 }
1014 object->size = size;
1015 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
1016 return SYNTAX_ERROR;
1017 }
1018 return DATA;
1019 }
1020 break;
1021 case 'f':
1022 if (!strcmp(tag, "false")) {
1023 if (tagType == TAG_EMPTY) {
1024 object->number = 0;
1025 return BOOLEAN;
1026 }
1027 }
1028 break;
1029 case 'i':
1030 if (!strcmp(tag, "integer")) {
1031 object->size = 64; // default
1032 for (i = 0; i < attributeCount; i++) {
1033 if (!strcmp(attributes[i], "size")) {
1034 object->size = strtoul(values[i], NULL, 0);
1035 }
1036 }
1037 if (tagType == TAG_EMPTY) {
1038 object->number = 0;
1039 return NUMBER;
1040 }
1041 object->number = getNumber(STATE);
1042 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
1043 return SYNTAX_ERROR;
1044 }
1045 return NUMBER;
1046 }
1047 break;
1048 case 'k':
1049 if (!strcmp(tag, "key")) {
1050 if (tagType == TAG_EMPTY) {
1051 return SYNTAX_ERROR;
1052 }
1053 object->string = getString(STATE, &alloc_length);
1054 if (!object->string) {
1055 return SYNTAX_ERROR;
1056 }
1057 object->string_alloc_length = alloc_length;
1058 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
1059 || strcmp(tag, "key")) {
1060 return SYNTAX_ERROR;
1061 }
1062 return KEY;
1063 }
1064 break;
1065 case 'p':
1066 if (!strcmp(tag, "plist")) {
1067 freeObject(STATE, object);
1068 goto top;
1069 }
1070 break;
1071 case 's':
1072 if (!strcmp(tag, "string")) {
1073 if (tagType == TAG_EMPTY) {
1074 object->string = (char *)malloc(1);
1075 object->string_alloc_length = 1;
1076 object->string[0] = 0;
1077 return STRING;
1078 }
1079 object->string = getString(STATE, &alloc_length);
1080 if (!object->string) {
1081 return SYNTAX_ERROR;
1082 }
1083 object->string_alloc_length = alloc_length;
1084 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
1085 || strcmp(tag, "string")) {
1086 return SYNTAX_ERROR;
1087 }
1088 return STRING;
1089 }
1090 if (!strcmp(tag, "set")) {
1091 if (tagType == TAG_EMPTY) {
1092 object->elements = NULL;
1093 return SET;
1094 }
1095 if (tagType == TAG_START) {
1096 return '[';
1097 } else {
1098 return ']';
1099 }
1100 }
1101 break;
1102 case 't':
1103 if (!strcmp(tag, "true")) {
1104 if (tagType == TAG_EMPTY) {
1105 object->number = 1;
1106 return BOOLEAN;
1107 }
1108 }
1109 break;
1110 }
1111
1112 return SYNTAX_ERROR;
1113 }
1114
1115 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1116 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1117 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1118
1119 // "java" like allocation, if this code hits a syntax error in the
1120 // the middle of the parsed string we just bail with pointers hanging
1121 // all over place, this code helps keeps it all together
1122
1123 //static int object_count = 0;
1124
1125 object_t *
newObject(parser_state_t * state)1126 newObject(parser_state_t *state)
1127 {
1128 object_t *o;
1129
1130 if (state->freeObjects) {
1131 o = state->freeObjects;
1132 state->freeObjects = state->freeObjects->next;
1133 } else {
1134 o = malloc_type(object_t);
1135 // object_count++;
1136 o->free = state->objects;
1137 state->objects = o;
1138 }
1139
1140 return o;
1141 }
1142
1143 void
freeObject(parser_state_t * state,object_t * o)1144 freeObject(parser_state_t * state, object_t *o)
1145 {
1146 o->next = state->freeObjects;
1147 state->freeObjects = o;
1148 }
1149
1150 void
cleanupObjects(parser_state_t * state)1151 cleanupObjects(parser_state_t *state)
1152 {
1153 object_t *t, *o = state->objects;
1154
1155 while (o) {
1156 if (o->object) {
1157 // printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
1158 o->object->release();
1159 }
1160 if (o->data) {
1161 // printf("OSUnserializeXML: freeing object o=%x data=%x\n", (int)o, (int)o->data);
1162 free(o->data);
1163 }
1164 if (o->key) {
1165 // printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
1166 o->key->release();
1167 }
1168 if (o->string) {
1169 // printf("OSUnserializeXML: freeing object o=%x string=%x\n", (int)o, (int)o->string);
1170 free(o->string);
1171 }
1172
1173 t = o;
1174 o = o->free;
1175 free_type(object_t, t);
1176 // object_count--;
1177 }
1178 // printf("object_count = %d\n", object_count);
1179 }
1180
1181 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1182 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1183 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1184
1185 static void
rememberObject(parser_state_t * state,int tag,OSObject * o)1186 rememberObject(parser_state_t *state, int tag, OSObject *o)
1187 {
1188 char key[16];
1189 snprintf(key, 16, "%u", tag);
1190
1191 // printf("remember key %s\n", key);
1192
1193 state->tags->setObject(key, o);
1194 }
1195
1196 static object_t *
retrieveObject(parser_state_t * state,int tag)1197 retrieveObject(parser_state_t *state, int tag)
1198 {
1199 OSObject *ref;
1200 object_t *o;
1201 char key[16];
1202 snprintf(key, 16, "%u", tag);
1203
1204 // printf("retrieve key '%s'\n", key);
1205
1206 ref = state->tags->getObject(key);
1207 if (!ref) {
1208 return 0;
1209 }
1210
1211 o = newObject(state);
1212 o->object = ref;
1213 return o;
1214 }
1215
1216 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1217 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1218 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1219
1220 object_t *
buildDictionary(parser_state_t * state,object_t * header)1221 buildDictionary(parser_state_t *state, object_t * header)
1222 {
1223 object_t *o, *t;
1224 int count = 0;
1225 OSDictionary *dict;
1226
1227 // get count and reverse order
1228 o = header->elements;
1229 header->elements = 0;
1230 while (o) {
1231 count++;
1232 t = o;
1233 o = o->next;
1234
1235 t->next = header->elements;
1236 header->elements = t;
1237 }
1238
1239 dict = OSDictionary::withCapacity(count);
1240 if (header->idref >= 0) {
1241 rememberObject(state, header->idref, dict);
1242 }
1243
1244 o = header->elements;
1245 while (o) {
1246 dict->setObject(o->key, o->object);
1247
1248 o->key->release();
1249 o->object->release();
1250 o->key = 0;
1251 o->object = 0;
1252
1253 t = o;
1254 o = o->next;
1255 freeObject(state, t);
1256 }
1257 o = header;
1258 o->object = dict;
1259 return o;
1260 };
1261
1262 object_t *
buildArray(parser_state_t * state,object_t * header)1263 buildArray(parser_state_t *state, object_t * header)
1264 {
1265 object_t *o, *t;
1266 int count = 0;
1267 OSArray *array;
1268
1269 // get count and reverse order
1270 o = header->elements;
1271 header->elements = 0;
1272 while (o) {
1273 count++;
1274 t = o;
1275 o = o->next;
1276
1277 t->next = header->elements;
1278 header->elements = t;
1279 }
1280
1281 array = OSArray::withCapacity(count);
1282 if (header->idref >= 0) {
1283 rememberObject(state, header->idref, array);
1284 }
1285
1286 o = header->elements;
1287 while (o) {
1288 array->setObject(o->object);
1289
1290 o->object->release();
1291 o->object = 0;
1292
1293 t = o;
1294 o = o->next;
1295 freeObject(state, t);
1296 }
1297 o = header;
1298 o->object = array;
1299 return o;
1300 };
1301
1302 object_t *
buildSet(parser_state_t * state,object_t * header)1303 buildSet(parser_state_t *state, object_t *header)
1304 {
1305 object_t *o = buildArray(state, header);
1306
1307 #if KERNEL
1308 OSArray *array = (OSArray *)o->object;
1309 OSSet *set = OSSet::withArray(array, array->getCapacity());
1310
1311 // write over the reference created in buildArray
1312 if (header->idref >= 0) {
1313 rememberObject(state, header->idref, set);
1314 }
1315
1316 array->release();
1317 o->object = set;
1318 #endif /* KERNEL */
1319 return o;
1320 };
1321
1322 object_t *
buildString(parser_state_t * state,object_t * o)1323 buildString(parser_state_t *state, object_t *o)
1324 {
1325 OSString *string;
1326
1327 string = OSString::withCString(o->string);
1328 if (o->idref >= 0) {
1329 rememberObject(state, o->idref, string);
1330 }
1331
1332 free(o->string);
1333 o->string = 0;
1334 o->object = string;
1335
1336 return o;
1337 };
1338
1339 object_t *
buildSymbol(parser_state_t * state,object_t * o)1340 buildSymbol(parser_state_t *state, object_t *o)
1341 {
1342 OSSymbol *symbol;
1343
1344 symbol = const_cast < OSSymbol * > (OSSymbol::withCString(o->string));
1345 if (o->idref >= 0) {
1346 rememberObject(state, o->idref, symbol);
1347 }
1348
1349 safe_free(o->string, o->string_alloc_length);
1350 o->string = 0;
1351 o->object = symbol;
1352
1353 return o;
1354 };
1355
1356 object_t *
buildData(parser_state_t * state,object_t * o)1357 buildData(parser_state_t *state, object_t *o)
1358 {
1359 OSData *data;
1360
1361 if (o->size) {
1362 data = OSData::withBytes(o->data, o->size);
1363 } else {
1364 data = OSData::withCapacity(0);
1365 }
1366 if (o->idref >= 0) {
1367 rememberObject(state, o->idref, data);
1368 }
1369
1370 if (o->size) {
1371 free(o->data);
1372 }
1373 o->data = 0;
1374 o->object = data;
1375 return o;
1376 };
1377
1378 object_t *
buildNumber(parser_state_t * state,object_t * o)1379 buildNumber(parser_state_t *state, object_t *o)
1380 {
1381 OSNumber *number = OSNumber::withNumber(o->number, o->size);
1382
1383 if (o->idref >= 0) {
1384 rememberObject(state, o->idref, number);
1385 }
1386
1387 o->object = number;
1388 return o;
1389 };
1390
1391 object_t *
buildBoolean(parser_state_t * state __unused,object_t * o)1392 buildBoolean(parser_state_t *state __unused, object_t *o)
1393 {
1394 o->object = ((o->number == 0) ? kOSBooleanFalse : kOSBooleanTrue);
1395 o->object->retain();
1396 return o;
1397 };
1398
1399 OSObject*
OSUnserializeXML(const char * buffer,OSString ** errorString)1400 OSUnserializeXML(const char *buffer, OSString **errorString)
1401 {
1402 OSObject *object;
1403
1404 if (!buffer) {
1405 return 0;
1406 }
1407 parser_state_t *state = (parser_state_t *)malloc_type(parser_state_t);
1408 if (!state) {
1409 return 0;
1410 }
1411
1412 // just in case
1413 if (errorString) {
1414 *errorString = NULL;
1415 }
1416
1417 state->parseBuffer = buffer;
1418 state->parseBufferIndex = 0;
1419 state->lineNumber = 1;
1420 state->objects = 0;
1421 state->freeObjects = 0;
1422 state->tags = OSDictionary::withCapacity(128);
1423 state->errorString = errorString;
1424 state->parsedObject = 0;
1425 state->parsedObjectCount = 0;
1426 state->retrievedObjectCount = 0;
1427
1428 (void)yyparse((void *)state);
1429
1430 object = state->parsedObject;
1431
1432 cleanupObjects(state);
1433 state->tags->release();
1434 free_type(parser_state_t, state);
1435
1436 return object;
1437 }
1438
1439 #if KERNEL
1440 #include <libkern/OSSerializeBinary.h>
1441
1442 OSObject*
OSUnserializeXML(const char * buffer,size_t bufferSize,OSString ** errorString)1443 OSUnserializeXML(const char *buffer, size_t bufferSize, OSString **errorString)
1444 {
1445 if (!buffer) {
1446 return 0;
1447 }
1448 if (bufferSize < sizeof(kOSSerializeBinarySignature)) {
1449 return 0;
1450 }
1451
1452 if (!strcmp(kOSSerializeBinarySignature, buffer)
1453 || (kOSSerializeIndexedBinarySignature == (uint8_t)buffer[0])) {
1454 return OSUnserializeBinary(buffer, bufferSize, errorString);
1455 }
1456
1457 // XML must be null terminated
1458 if (buffer[bufferSize - 1]) {
1459 return 0;
1460 }
1461
1462 return OSUnserializeXML(buffer, errorString);
1463 }
1464
1465 #else /* !KERNEL */
1466
1467 OSObject*
OSUnserializeXML(const char * buffer,size_t bufferSize,OSString ** errorString)1468 OSUnserializeXML(const char *buffer, size_t bufferSize, OSString **errorString)
1469 {
1470 if (!buffer) {
1471 return 0;
1472 }
1473
1474 // XML must be null terminated
1475 if (buffer[bufferSize - 1]) {
1476 return 0;
1477 }
1478
1479 return OSUnserializeXML(buffer, errorString);
1480 }
1481
1482 #endif /* KERNEL */
1483
1484
1485 //
1486 //
1487 //
1488 //
1489 //
1490 // DO NOT EDIT OSUnserializeXMLSharedImplementation.h!
1491 //
1492 // this means you!
1493 //
1494 //
1495 //
1496 //
1497 //
1498