/*
- * 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
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
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);
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);
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)
/* Line 216 of yacc.c. */
-#line 216 "OSUnserializeXML.tab.c"
+#line 215 "OSUnserializeXML.tab.c"
#ifdef short
# undef short
#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)
};
/* 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
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, \
/* 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
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)]));
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;
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)]);
;}
/* Line 1267 of yacc.c. */
-#line 1600 "OSUnserializeXML.tab.c"
+#line 1699 "OSUnserializeXML.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
}
-#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;
}
#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])
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;
values[*attributeCount][length++] = c;
if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
c = nextChar();
+ if (!c) return TAG_BAD;
}
values[*attributeCount][length] = 0;
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);
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)
{
};
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();
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;
state->tags = OSDictionary::withCapacity(128);
state->errorString = errorString;
state->parsedObject = 0;
+ state->parsedObjectCount = 0;
+ state->retrievedObjectCount = 0;
(void)yyparse((void *)state);
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);
+}
+
//
//