Fixed: crash in - CPArray/CPDictionary description containing self referential JS object.

Without this fix, certain JS contents could cause `- CPDictionary description` and `- CPArray description` to crash.

This change limits how deeply the description code will recurse before returning a default "…" description.
This commit is contained in:
Alexander Ljungberg committed 2013-06-13 20:14:22 +01:00
1 parent 22905745f1
commit e59389b0dd
5 files changed
+41 -5

No files matched your search

+8 -1
View File
@@ -37,6 +37,8 @@ CPBinarySearchingFirstEqual = 1 << 8;
CPBinarySearchingLastEqual = 1 << 9;
CPBinarySearchingInsertionIndex = 1 << 10;
var CPArrayMaxDescriptionRecursion = 10;
var concat = Array.prototype.concat,
join = Array.prototype.join,
push = Array.prototype.push;
@@ -874,6 +876,11 @@ var concat = Array.prototype.concat,
Returns a human readable description of this array and it's elements.
*/
- (CPString)description
{
return [self _descriptionWithMaximumDepth:CPArrayMaxDescriptionRecursion];
}
- (CPString)_descriptionWithMaximumDepth:(int)maximumDepth
{
var index = 0,
count = [self count],
@@ -887,7 +894,7 @@ var concat = Array.prototype.concat,
var object = [self objectAtIndex:index];
// NOTE: replace(/^/mg, " ") inserts 4 spaces at the beginning of every line
description += CPDescriptionOfObject(object).replace(/^/mg, " ");
description += CPDescriptionOfObject(object, maximumDepth).replace(/^/mg, " ");
if (index < count - 1)
description += ",\n";
+4 -2
View File
@@ -27,7 +27,9 @@
@import "CPObject.j"
//FIXME: After release of 0.9.7 remove below variable
var CPDictionaryShowNilDeprecationMessage = YES;
var CPDictionaryShowNilDeprecationMessage = YES,
CPDictionaryMaxDescriptionRecursion = 10;
/* @ignore */
@implementation _CPDictionaryValueEnumerator : CPEnumerator
@@ -733,7 +735,7 @@ var CPDictionaryShowNilDeprecationMessage = YES;
var key = keys[index],
value = self.valueForKey(key);
string += " @\"" + key + "\": " + CPDescriptionOfObject(value).split("\n").join("\n ") + (index + 1 < count ? "," : "") + "\n";
string += " @\"" + key + "\": " + CPDescriptionOfObject(value, CPDictionaryMaxDescriptionRecursion).split("\n").join("\n ") + (index + 1 < count ? "," : "") + "\n";
}
return string + "}";
+11 -2
View File
@@ -536,7 +536,7 @@ CPLog(@"Got some class: %@", inst);
@end
function CPDescriptionOfObject(anObject)
function CPDescriptionOfObject(anObject, maximumRecursionDepth)
{
if (anObject === nil)
return "nil";
@@ -547,11 +547,17 @@ function CPDescriptionOfObject(anObject)
if (anObject === window)
return "window";
if (maximumRecursionDepth === 0)
return "...";
if (anObject.isa)
{
if ([anObject isKindOfClass:CPString])
return '@"' + [anObject description] + '"';
if ([anObject respondsToSelector:@selector(_descriptionWithMaximumDepth:)])
return [anObject _descriptionWithMaximumDepth:maximumRecursionDepth !== undefined ? maximumRecursionDepth - 1 : maximumRecursionDepth];
return [anObject description];
}
@@ -584,7 +590,10 @@ function CPDescriptionOfObject(anObject)
if (i === 0)
desc += "\n";
desc += " " + properties[i] + ": " + CPDescriptionOfObject(anObject[properties[i]]).split("\n").join("\n ");
var value = anObject[properties[i]],
valueDescription = CPDescriptionOfObject(value, maximumRecursionDepth !== undefined ? maximumRecursionDepth - 1 : maximumRecursionDepth).split("\n").join("\n ");
desc += " " + properties[i] + ": " + valueDescription;
if (i < properties.length - 1)
desc += ",\n";
+9
View File
@@ -641,6 +641,15 @@
[self assertTrue:d.indexOf("(5, 6)") !== -1 message:"Can't find '(5, 6)' in description of array " + d];
}
- (void)testRecursiveJSObjectDescription
{
var a = [];
a.push(a);
[self assert:'@[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n ...\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n]' equals:[a description]];
}
- (void)testSortUsingDescriptorsWithDifferentSelectors
{
var a = [CPDictionary dictionaryWithJSObject:{"a": "AB", "b": "ba"}],
+9
View File
@@ -408,6 +408,15 @@
[self assert:'@{\n @"Key": window\n}' equals:[dict description]];
}
- (void)testRecursiveJSObjectDescription
{
var a = {};
a['a'] = a;
[self assert:'@{\n @"a": {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: ...\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}' equals:[@{ 'a': a } description]];
}
- (void)testInitWithObjectsAndKeys
{
var dict = [[CPDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", nil, @"Key2", @"Value3", @"Key3"];