]> git.saurik.com Git - apple/xnu.git/blobdiff - libkern/c++/OSUnserializeXML.cpp
xnu-4570.1.46.tar.gz
[apple/xnu.git] / libkern / c++ / OSUnserializeXML.cpp
index e543deec561a4b121f1ec6d717e024513704fe9e..e44bee927c4c96df53e90af981c0de2caa69f310 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 1999-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
 #include <libkern/c++/OSContainers.h>
 #include <libkern/c++/OSLib.h>
 
+#define MAX_OBJECTS             131071
+#define MAX_REFED_OBJECTS       65535
+
 #define YYSTYPE object_t *
 #define YYPARSE_PARAM  state
 #define YYLEX_PARAM    (parser_state_t *)state
@@ -170,7 +173,7 @@ typedef     struct object {
        struct object   *free;
        struct object   *elements;
        OSObject        *object;
-       OSString        *key;                   // for dictionary
+       OSSymbol        *key;                   // for dictionary
        int             size;
        void            *data;                  // for data
        char            *string;                // for string & symbol
@@ -189,16 +192,17 @@ typedef struct parser_state {
        OSDictionary    *tags;                  // used to remember "ID" tags
        OSString        **errorString;          // parse error with line
        OSObject        *parsedObject;          // resultant object of parsed text
+       int             parsedObjectCount;
+       int             retrievedObjectCount;
 } parser_state_t;
 
 #define STATE          ((parser_state_t *)state)
 
 #undef yyerror         
 #define yyerror(s)     OSUnserializeerror(STATE, (s))
-static int             OSUnserializeerror(parser_state_t *state, char *s);
+static int             OSUnserializeerror(parser_state_t *state, const char *s);
 
 static int             yylex(YYSTYPE *lvalp, parser_state_t *state);
-static int             yyparse(void * state);
 
 static object_t        *newObject(parser_state_t *state);
 static void            freeObject(parser_state_t *state, object_t *o);
@@ -210,6 +214,7 @@ static object_t             *buildDictionary(parser_state_t *state, object_t *o);
 static object_t                *buildArray(parser_state_t *state, object_t *o);
 static object_t                *buildSet(parser_state_t *state, object_t *o);
 static object_t                *buildString(parser_state_t *state, object_t *o);
+static object_t                *buildSymbol(parser_state_t *state, object_t *o);
 static object_t                *buildData(parser_state_t *state, object_t *o);
 static object_t                *buildNumber(parser_state_t *state, object_t *o);
 static object_t                *buildBoolean(parser_state_t *state, object_t *o);
@@ -219,10 +224,6 @@ extern void                *kern_os_malloc(size_t size);
 extern void            *kern_os_realloc(void * addr, size_t size);
 extern void            kern_os_free(void * addr);
 
-//XXX shouldn't have to define these
-extern long            strtol(const char *, char **, int);
-extern unsigned long   strtoul(const char *, char **, int);
-
 } /* extern "C" */
 
 #define malloc(s) kern_os_malloc(s)
@@ -262,7 +263,7 @@ typedef int YYSTYPE;
 
 
 /* Line 216 of yacc.c.  */
-#line 216 "OSUnserializeXML.tab.c"
+#line 215 "OSUnserializeXML.tab.c"
 
 #ifdef short
 # undef short
@@ -312,7 +313,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -552,12 +553,12 @@ static const yytype_int8 yyrhs[] =
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
+static const yytype_uint16 yyrline[] =
 {
-       0,   150,   150,   153,   158,   163,   164,   165,   166,   167,
-     168,   169,   170,   183,   186,   189,   192,   193,   198,   207,
-     212,   215,   218,   221,   224,   227,   230,   233,   240,   243,
-     246,   249,   252
+       0,   149,   149,   152,   157,   162,   174,   186,   198,   210,
+     222,   234,   246,   265,   268,   271,   274,   275,   290,   299,
+     311,   314,   317,   320,   323,   326,   329,   332,   339,   342,
+     345,   348,   351
 };
 #endif
 
@@ -754,7 +755,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)                 \
      fprintf (File, "%d.%d-%d.%d",                     \
              (Loc).first_line, (Loc).first_column,     \
@@ -936,7 +937,7 @@ int yydebug;
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
 #ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
+# define YYINITDEPTH 64
 #endif
 
 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
@@ -1495,14 +1496,14 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 150 "OSUnserializeXML.y"
+#line 149 "OSUnserializeXML.y"
     { yyerror("unexpected end of buffer");
                                  YYERROR;
                                ;}
     break;
 
   case 3:
-#line 153 "OSUnserializeXML.y"
+#line 152 "OSUnserializeXML.y"
     { STATE->parsedObject = (yyvsp[(1) - (1)])->object;
                                  (yyvsp[(1) - (1)])->object = 0;
                                  freeObject(STATE, (yyvsp[(1) - (1)]));
@@ -1511,85 +1512,183 @@ yyreduce:
     break;
 
   case 4:
-#line 158 "OSUnserializeXML.y"
+#line 157 "OSUnserializeXML.y"
     { yyerror("syntax error");
                                  YYERROR;
                                ;}
     break;
 
   case 5:
-#line 163 "OSUnserializeXML.y"
-    { (yyval) = buildDictionary(STATE, (yyvsp[(1) - (1)])); ;}
+#line 162 "OSUnserializeXML.y"
+    { (yyval) = buildDictionary(STATE, (yyvsp[(1) - (1)]));
+
+                                 if (!yyval->object) {
+                                   yyerror("buildDictionary");
+                                   YYERROR;
+                                 }
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
+                               ;}
     break;
 
   case 6:
-#line 164 "OSUnserializeXML.y"
-    { (yyval) = buildArray(STATE, (yyvsp[(1) - (1)])); ;}
+#line 174 "OSUnserializeXML.y"
+    { (yyval) = buildArray(STATE, (yyvsp[(1) - (1)]));
+
+                                 if (!yyval->object) {
+                                   yyerror("buildArray");
+                                   YYERROR;
+                                 }
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
+                               ;}
     break;
 
   case 7:
-#line 165 "OSUnserializeXML.y"
-    { (yyval) = buildSet(STATE, (yyvsp[(1) - (1)])); ;}
+#line 186 "OSUnserializeXML.y"
+    { (yyval) = buildSet(STATE, (yyvsp[(1) - (1)]));
+
+                                 if (!yyval->object) {
+                                   yyerror("buildSet");
+                                   YYERROR;
+                                 }
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
+                               ;}
     break;
 
   case 8:
-#line 166 "OSUnserializeXML.y"
-    { (yyval) = buildString(STATE, (yyvsp[(1) - (1)])); ;}
+#line 198 "OSUnserializeXML.y"
+    { (yyval) = buildString(STATE, (yyvsp[(1) - (1)]));
+
+                                 if (!yyval->object) {
+                                   yyerror("buildString");
+                                   YYERROR;
+                                 }
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
+                               ;}
     break;
 
   case 9:
-#line 167 "OSUnserializeXML.y"
-    { (yyval) = buildData(STATE, (yyvsp[(1) - (1)])); ;}
+#line 210 "OSUnserializeXML.y"
+    { (yyval) = buildData(STATE, (yyvsp[(1) - (1)]));
+
+                                 if (!yyval->object) {
+                                   yyerror("buildData");
+                                   YYERROR;
+                                 }
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
+                               ;}
     break;
 
   case 10:
-#line 168 "OSUnserializeXML.y"
-    { (yyval) = buildNumber(STATE, (yyvsp[(1) - (1)])); ;}
+#line 222 "OSUnserializeXML.y"
+    { (yyval) = buildNumber(STATE, (yyvsp[(1) - (1)]));
+
+                                 if (!yyval->object) {
+                                   yyerror("buildNumber");
+                                   YYERROR;
+                                 }
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
+                               ;}
     break;
 
   case 11:
-#line 169 "OSUnserializeXML.y"
-    { (yyval) = buildBoolean(STATE, (yyvsp[(1) - (1)])); ;}
+#line 234 "OSUnserializeXML.y"
+    { (yyval) = buildBoolean(STATE, (yyvsp[(1) - (1)]));
+
+                                 if (!yyval->object) {
+                                   yyerror("buildBoolean");
+                                   YYERROR;
+                                 }
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
+                               ;}
     break;
 
   case 12:
-#line 170 "OSUnserializeXML.y"
+#line 246 "OSUnserializeXML.y"
     { (yyval) = retrieveObject(STATE, (yyvsp[(1) - (1)])->idref);
                                  if ((yyval)) {
+                                   STATE->retrievedObjectCount++;
+                                   if (STATE->retrievedObjectCount > MAX_REFED_OBJECTS) {
+                                     yyerror("maximum object reference count");
+                                     YYERROR;
+                                   }
                                    (yyval)->object->retain();
                                  } else { 
                                    yyerror("forward reference detected");
                                    YYERROR;
                                  }
                                  freeObject(STATE, (yyvsp[(1) - (1)]));
+
+                                 STATE->parsedObjectCount++;
+                                 if (STATE->parsedObjectCount > MAX_OBJECTS) {
+                                   yyerror("maximum object count");
+                                   YYERROR;
+                                 }
                                ;}
     break;
 
   case 13:
-#line 183 "OSUnserializeXML.y"
+#line 265 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (2)]);
                                  (yyval)->elements = NULL;
                                ;}
     break;
 
   case 14:
-#line 186 "OSUnserializeXML.y"
+#line 268 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (3)]);
                                  (yyval)->elements = (yyvsp[(2) - (3)]);
                                ;}
     break;
 
   case 17:
-#line 193 "OSUnserializeXML.y"
+#line 275 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(2) - (2)]);
                                  (yyval)->next = (yyvsp[(1) - (2)]);
+
+                                 object_t *o;
+                                 o = (yyval)->next;
+                                 while (o) {
+                                   if (o->key == (yyval)->key) {
+                                     yyerror("duplicate dictionary key");
+                                     YYERROR;
+                                   }
+                                   o = o->next;
+                                 }
                                ;}
     break;
 
   case 18:
-#line 198 "OSUnserializeXML.y"
+#line 290 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (2)]);
-                                 (yyval)->key = (OSString *)(yyval)->object;
+                                 (yyval)->key = (OSSymbol *)(yyval)->object;
                                  (yyval)->object = (yyvsp[(2) - (2)])->object;
                                  (yyval)->next = NULL; 
                                  (yyvsp[(2) - (2)])->object = 0;
@@ -1598,47 +1697,54 @@ yyreduce:
     break;
 
   case 19:
-#line 207 "OSUnserializeXML.y"
-    { (yyval) = buildString(STATE, (yyvsp[(1) - (1)])); ;}
+#line 299 "OSUnserializeXML.y"
+    { (yyval) = buildSymbol(STATE, (yyvsp[(1) - (1)]));
+
+//                               STATE->parsedObjectCount++;
+//                               if (STATE->parsedObjectCount > MAX_OBJECTS) {
+//                                 yyerror("maximum object count");
+//                                 YYERROR;
+//                               }
+                               ;}
     break;
 
   case 20:
-#line 212 "OSUnserializeXML.y"
+#line 311 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (2)]);
                                  (yyval)->elements = NULL;
                                ;}
     break;
 
   case 21:
-#line 215 "OSUnserializeXML.y"
+#line 314 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (3)]);
                                  (yyval)->elements = (yyvsp[(2) - (3)]);
                                ;}
     break;
 
   case 23:
-#line 221 "OSUnserializeXML.y"
+#line 320 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (2)]);
                                  (yyval)->elements = NULL;
                                ;}
     break;
 
   case 24:
-#line 224 "OSUnserializeXML.y"
+#line 323 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (3)]);
                                  (yyval)->elements = (yyvsp[(2) - (3)]);
                                ;}
     break;
 
   case 26:
-#line 230 "OSUnserializeXML.y"
+#line 329 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(1) - (1)]); 
                                  (yyval)->next = NULL; 
                                ;}
     break;
 
   case 27:
-#line 233 "OSUnserializeXML.y"
+#line 332 "OSUnserializeXML.y"
     { (yyval) = (yyvsp[(2) - (2)]);
                                  (yyval)->next = (yyvsp[(1) - (2)]);
                                ;}
@@ -1646,7 +1752,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 1600 "OSUnserializeXML.tab.c"
+#line 1699 "OSUnserializeXML.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1860,19 +1966,18 @@ yyreturn:
 }
 
 
-#line 255 "OSUnserializeXML.y"
+#line 354 "OSUnserializeXML.y"
 
 
 int
-OSUnserializeerror(parser_state_t * state, char *s)  /* Called by yyparse on errors */
+OSUnserializeerror(parser_state_t * state, const char *s)  /* Called by yyparse on errors */
 {
-    char tempString[128];
-
     if (state->errorString) {
+       char tempString[128];
        snprintf(tempString, 128, "OSUnserializeXML: %s near line %d\n", s, state->lineNumber);
        *(state->errorString) = OSString::withCString(tempString);
     }
-
+    
     return 0;
 }
 
@@ -1882,7 +1987,7 @@ OSUnserializeerror(parser_state_t * state, char *s)  /* Called by yyparse on err
 #define TAG_START              1
 #define TAG_END                        2
 #define TAG_EMPTY              3
-#define TAG_COMMENT            4
+#define TAG_IGNORE             4
 
 #define currentChar()  (state->parseBuffer[state->parseBufferIndex])
 #define nextChar()     (state->parseBuffer[++state->parseBufferIndex])
@@ -1911,16 +2016,51 @@ getTag(parser_state_t *state,
        if (c != '<') return TAG_BAD;
         c = nextChar();                // skip '<'
 
-        if (c == '?' || c == '!') {
-                while ((c = nextChar()) != 0) {
-                        if (c == '\n') state->lineNumber++;
-                        if (c == '>') {
-                                (void)nextChar();
-                                return TAG_COMMENT;
-                        }
-                }
-        }
 
+       // <!TAG   declarations     >
+       // <!--     comments      -->
+        if (c == '!') {
+           c = nextChar();  
+           bool isComment = (c == '-') && ((c = nextChar()) != 0) && (c == '-');
+           if (!isComment && !isAlpha(c)) return TAG_BAD;   // <!1, <!-A, <!eos
+
+           while (c && (c = nextChar()) != 0) {
+               if (c == '\n') state->lineNumber++;
+               if (isComment) {
+                   if (c != '-') continue;
+                   c = nextChar();
+                   if (c != '-') continue;
+                   c = nextChar();
+               }
+               if (c == '>') {
+                   (void)nextChar();
+                   return TAG_IGNORE;
+               }
+               if (isComment) break;
+           }
+           return TAG_BAD;
+       }
+
+       else
+
+       // <? Processing Instructions  ?>
+        if (c == '?') {
+           while ((c = nextChar()) != 0) {
+               if (c == '\n') state->lineNumber++;
+               if (c != '?') continue;
+               c = nextChar();
+               if (!c) return TAG_IGNORE;
+               if (c == '>') {
+                   (void)nextChar();
+                   return TAG_IGNORE;
+               }
+           }
+           return TAG_BAD;
+       }
+
+       else
+
+       // </ end tag >    
        if (c == '/') {
                c = nextChar();         // skip '/'
                tagType = TAG_END;
@@ -1964,6 +2104,7 @@ getTag(parser_state_t *state,
                        values[*attributeCount][length++] = c;
                        if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
                        c = nextChar();
+                       if (!c) return TAG_BAD;
                }
                values[*attributeCount][length] = 0;
 
@@ -2255,7 +2396,7 @@ yylex(YYSTYPE *lvalp, parser_state_t *state)
 
        tagType = getTag(STATE, tag, &attributeCount, attributes, values);
        if (tagType == TAG_BAD) return SYNTAX_ERROR;
-       if (tagType == TAG_COMMENT) goto top;
+       if (tagType == TAG_IGNORE) goto top;
 
        // handle allocation and check for "ID" and "IDREF" tags up front
        *lvalp = object = newObject(STATE);
@@ -2628,6 +2769,21 @@ buildString(parser_state_t *state, object_t *o)
        return o;
 };
 
+object_t *
+buildSymbol(parser_state_t *state, object_t *o)
+{
+       OSSymbol *symbol;
+
+       symbol = (OSSymbol *)OSSymbol::withCString(o->string);
+       if (o->idref >= 0) rememberObject(state, o->idref, symbol);
+
+       free(o->string);
+       o->string = 0;
+       o->object = symbol;
+
+       return o;
+};
+
 object_t *
 buildData(parser_state_t *state, object_t *o)
 {
@@ -2658,7 +2814,7 @@ buildNumber(parser_state_t *state, object_t *o)
 };
 
 object_t *
-buildBoolean(parser_state_t *state, object_t *o)
+buildBoolean(parser_state_t *state __unused, object_t *o)
 {
        o->object = ((o->number == 0) ? kOSBooleanFalse : kOSBooleanTrue);
        o->object->retain();
@@ -2669,9 +2825,10 @@ OSObject*
 OSUnserializeXML(const char *buffer, OSString **errorString)
 {
        OSObject *object;
-       parser_state_t *state = (parser_state_t *)malloc(sizeof(parser_state_t));
 
-       if ((!state) || (!buffer)) return 0;
+       if (!buffer) return 0;
+       parser_state_t *state = (parser_state_t *)malloc(sizeof(parser_state_t));
+       if (!state) return 0;
 
        // just in case
        if (errorString) *errorString = NULL;
@@ -2684,6 +2841,8 @@ OSUnserializeXML(const char *buffer, OSString **errorString)
        state->tags = OSDictionary::withCapacity(128);
        state->errorString = errorString;
        state->parsedObject = 0;
+       state->parsedObjectCount = 0;
+       state->retrievedObjectCount = 0;
 
        (void)yyparse((void *)state);
 
@@ -2696,6 +2855,22 @@ OSUnserializeXML(const char *buffer, OSString **errorString)
        return object;
 }
 
+#include <libkern/OSSerializeBinary.h>
+
+OSObject*
+OSUnserializeXML(const char *buffer, size_t bufferSize, OSString **errorString)
+{
+       if (!buffer) return (0);
+    if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (0);
+
+       if (!strcmp(kOSSerializeBinarySignature, buffer)) return OSUnserializeBinary(buffer, bufferSize, errorString);
+
+       // XML must be null terminated
+       if (buffer[bufferSize - 1]) return 0;
+
+       return OSUnserializeXML(buffer, errorString);
+}
+
 
 //
 //