Fix stack overflow.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@17453 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2003-08-07 18:22:03 +00:00
parent 6acd869d7b
commit 76b458f3e8
3 changed files with 132 additions and 126 deletions

View file

@ -3,7 +3,11 @@
* Source/NSString.m: nodeToObject() fix error in handling escape * Source/NSString.m: nodeToObject() fix error in handling escape
sequences in strings ... only treat a backslash specially when it sequences in strings ... only treat a backslash specially when it
is immediately followed by 'U' or 'u' and four hexadecimal digits. is immediately followed by 'U' or 'u' and four hexadecimal digits.
ensure data ia deallocated promptly.
* Source/GSCompatibility.m: match changes to property list escapes * Source/GSCompatibility.m: match changes to property list escapes
* Source/Additions/GSXML.m: change ownership policy so that nodes
are owned by theri parents, never by siblings ... prevent stack
overflow deallocating nodes in long documents.
* Tools/plist-0_9.dtd: document unicode escapes. * Tools/plist-0_9.dtd: document unicode escapes.
2003-08-02 Adam Fedor <fedor@gnu.org> 2003-08-02 Adam Fedor <fedor@gnu.org>

View file

@ -1340,7 +1340,7 @@ static NSMapTable *nodeNames = 0;
{ {
GSXMLNode *n = [GSXMLNode alloc]; GSXMLNode *n = [GSXMLNode alloc];
n = [n _initFrom: ((xmlNodePtr)(lib))->next parent: self]; n = [n _initFrom: ((xmlNodePtr)(lib))->next parent: _parent];
return AUTORELEASE(n); return AUTORELEASE(n);
} }
else else
@ -1367,7 +1367,7 @@ static NSMapTable *nodeNames = 0;
{ {
GSXMLNode *n = [GSXMLNode alloc]; GSXMLNode *n = [GSXMLNode alloc];
n = [n _initFrom: ptr parent: self]; n = [n _initFrom: ptr parent: _parent];
return AUTORELEASE(n); return AUTORELEASE(n);
} }
} }
@ -1476,7 +1476,7 @@ static NSMapTable *nodeNames = 0;
{ {
GSXMLNode *n = [GSXMLNode alloc]; GSXMLNode *n = [GSXMLNode alloc];
n = [n _initFrom: ((xmlNodePtr)(lib))->prev parent: self]; n = [n _initFrom: ((xmlNodePtr)(lib))->prev parent: _parent];
return AUTORELEASE(n); return AUTORELEASE(n);
} }
else else
@ -1501,7 +1501,7 @@ static NSMapTable *nodeNames = 0;
{ {
GSXMLNode *n = [GSXMLNode alloc]; GSXMLNode *n = [GSXMLNode alloc];
n = [n _initFrom: ptr parent: self]; n = [n _initFrom: ptr parent: _parent];
return AUTORELEASE(n); return AUTORELEASE(n);
} }
} }

View file

@ -46,6 +46,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "GNUstepBase/preface.h" #include "GNUstepBase/preface.h"
#include "Foundation/NSAutoreleasePool.h"
#include "Foundation/NSString.h" #include "Foundation/NSString.h"
#include "Foundation/NSCalendarDate.h" #include "Foundation/NSCalendarDate.h"
#include "Foundation/NSArray.h" #include "Foundation/NSArray.h"
@ -4988,163 +4989,164 @@ elementNode(GSXMLNode* node)
static id static id
nodeToObject(GSXMLNode* node) nodeToObject(GSXMLNode* node)
{ {
NSString *name; CREATE_AUTORELEASE_POOL(arp);
NSString *content; id result = nil;
GSXMLNode *children;
node = elementNode(node); node = elementNode(node);
if (node == nil) if (node != nil)
{ {
return nil; NSString *name;
} NSString *content;
name = [node name]; GSXMLNode *children;
children = [node firstChild];
content = [children content];
children = elementNode(children);
if ([name isEqualToString: @"string"] name = [node name];
|| [name isEqualToString: @"key"]) children = [node firstChild];
{ content = [children content];
if (content == nil) children = elementNode(children);
{
content = @"";
}
else
{
NSRange r;
r = [content rangeOfString: @"\\"]; if ([name isEqualToString: @"string"]
if (r.length == 1) || [name isEqualToString: @"key"])
{
if (content == nil)
{ {
unsigned len = [content length]; content = @"";
unichar buf[len]; }
unsigned pos = r.location; else
{
NSRange r;
[content getCharacters: buf]; r = [content rangeOfString: @"\\"];
while (pos < len) if (r.length == 1)
{ {
if (++pos < len) unsigned len = [content length];
unichar buf[len];
unsigned pos = r.location;
[content getCharacters: buf];
while (pos < len)
{ {
if ((buf[pos] == 'u' || buf[pos] == 'U') if (++pos < len)
&& (len >= pos + 4))
{ {
unichar val = 0; if ((buf[pos] == 'u' || buf[pos] == 'U')
unsigned i; && (len >= pos + 4))
BOOL ok = YES;
for (i = 1; i < 5; i++)
{ {
unichar c = buf[pos + i]; unichar val = 0;
unsigned i;
BOOL ok = YES;
if (c >= '0' && c <= '9') for (i = 1; i < 5; i++)
{ {
val = (val << 4) + c - '0'; unichar c = buf[pos + i];
if (c >= '0' && c <= '9')
{
val = (val << 4) + c - '0';
}
else if (c >= 'A' && c <= 'F')
{
val = (val << 4) + c - 'A' + 10;
}
else if (c >= 'a' && c <= 'f')
{
val = (val << 4) + c - 'a' + 10;
}
else
{
ok = NO;
}
} }
else if (c >= 'A' && c <= 'F') if (ok == YES)
{ {
val = (val << 4) + c - 'A' + 10; len -= 5;
} memcpy(&buf[pos], &buf[pos+5],
else if (c >= 'a' && c <= 'f') (len - pos) * sizeof(unichar));
{ buf[pos - 1] = val;
val = (val << 4) + c - 'a' + 10;
}
else
{
ok = NO;
} }
} }
if (ok == YES) while (pos < len && buf[pos] != '\\')
{ {
len -= 5; pos++;
memcpy(&buf[pos], &buf[pos+5],
(len - pos) * sizeof(unichar));
buf[pos - 1] = val;
} }
} }
while (pos < len && buf[pos] != '\\')
{
pos++;
}
} }
content = [NSString stringWithCharacters: buf length: len];
} }
content = [NSString stringWithCharacters: buf length: len];
} }
result = content;
} }
return content; else if ([name isEqualToString: @"true"])
}
else if ([name isEqualToString: @"true"])
{
return [NSNumber numberWithBool: YES];
}
else if ([name isEqualToString: @"false"])
{
return [NSNumber numberWithBool: NO];
}
else if ([name isEqualToString: @"integer"])
{
if (content == nil)
{ {
content = @"0"; result = [NSNumber numberWithBool: YES];
} }
return [NSNumber numberWithInt: [content intValue]]; else if ([name isEqualToString: @"false"])
}
else if ([name isEqualToString: @"real"])
{
if (content == nil)
{ {
content = @"0.0"; result = [NSNumber numberWithBool: NO];
} }
return [NSNumber numberWithDouble: [content doubleValue]]; else if ([name isEqualToString: @"integer"])
}
else if ([name isEqualToString: @"date"])
{
if (content == nil)
{ {
content = @""; if (content == nil)
{
content = @"0";
}
result = [NSNumber numberWithInt: [content intValue]];
} }
return [NSCalendarDate dateWithString: content else if ([name isEqualToString: @"real"])
calendarFormat: @"%Y-%m-%d %H:%M:%S %z"]; {
} if (content == nil)
else if ([name isEqualToString: @"data"]) {
{ content = @"0.0";
return [GSMimeDocument decodeBase64String: content]; }
} result = [NSNumber numberWithDouble: [content doubleValue]];
// container class }
else if ([name isEqualToString: @"array"]) else if ([name isEqualToString: @"date"])
{ {
NSMutableArray *container = [NSMutableArray array]; if (content == nil)
{
content = @"";
}
result = [NSCalendarDate dateWithString: content
calendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
}
else if ([name isEqualToString: @"data"])
{
result = [GSMimeDocument decodeBase64String: content];
}
// container class
else if ([name isEqualToString: @"array"])
{
NSMutableArray *container = [NSMutableArray array];
while (children != nil) while (children != nil)
{ {
id val; id val;
val = nodeToObject(children); val = nodeToObject(children);
[container addObject: val]; [container addObject: val];
children = elementNode([children next]); children = [children nextElement];
} }
return container; result = container;
} }
else if ([name isEqualToString: @"dict"]) else if ([name isEqualToString: @"dict"])
{ {
NSMutableDictionary *container = [NSMutableDictionary dictionary]; NSMutableDictionary *container = [NSMutableDictionary dictionary];
while (children != nil) while (children != nil)
{ {
NSString *key; NSString *key;
id val; id val;
key = nodeToObject(children); key = nodeToObject(children);
children = elementNode([children next]); children = [children nextElement];
val = nodeToObject(children); val = nodeToObject(children);
children = elementNode([children next]); children = [children nextElement];
[container setObject: val forKey: key]; [container setObject: val forKey: key];
} }
return container; result = container;
} }
else
{
return nil;
} }
RETAIN(result);
RELEASE(arp);
return AUTORELEASE(result);
} }
#endif #endif