Skip to content

Commit 18a0a3a

Browse files
committed
Fixes a bug when trying to retrieve a key from a dictionary that contains no items (div by zero: (keyHash % dictionary->capacity))
1 parent 635005b commit 18a0a3a

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

JSONKit.m

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ - (NSUInteger)count
966966

967967
static JKHashTableEntry *_JKDictionaryHashTableEntryForKey(JKDictionary *dictionary, id aKey) {
968968
NSCParameterAssert((dictionary != NULL) && (dictionary->entry != NULL) && (dictionary->count <= dictionary->capacity));
969-
if(aKey == NULL) { return(NULL); }
969+
if((aKey == NULL) || (dictionary->capacity == 0UL)) { return(NULL); }
970970
NSUInteger keyHash = CFHash(aKey), keyEntry = (keyHash % dictionary->capacity), idx = 0UL;
971971
JKHashTableEntry *atEntry = NULL;
972972
for(idx = 0UL; idx < dictionary->capacity; idx++) {
@@ -2525,6 +2525,7 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
25252525
return(0);
25262526
}
25272527

2528+
#if 0
25282529
// When we encounter a class that we do not handle, and we have either a delegate or block that the user supplied to format unsupported classes,
25292530
// we "re-run" the object check. However, we re-run the object check exactly ONCE. If the user supplies an object that isn't one of the
25302531
// supported classes, we fail the second type (i.e., double fault error).
@@ -2552,7 +2553,39 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
25522553
else { jk_encode_error(encodeState, @"Unable to serialize object class %@ that was returned by the unsupported class formatter. Original object class was %@.", (object == NULL) ? @"NULL" : NSStringFromClass([object class]), NSStringFromClass([encodeCacheObject class])); return(1); }
25532554
}
25542555
}
2556+
#else
25552557

2558+
// When we encounter a class that we do not handle, and we have either a delegate or block that the user supplied to format unsupported classes,
2559+
// we "re-run" the object check. However, we re-run the object check exactly ONCE. If the user supplies an object that isn't one of the
2560+
// supported classes, we fail the second type (i.e., double fault error).
2561+
//BOOL rerunningAfterClassFormatter = NO;
2562+
//rerunAfterClassFormatter:
2563+
2564+
if(
2565+
#ifdef __BLOCKS__
2566+
((encodeState->classFormatterBlock) && ((object = encodeState->classFormatterBlock(object)) == NULL)) ||
2567+
#endif
2568+
((encodeState->classFormatterIMP) && ((object = encodeState->classFormatterIMP(encodeState->classFormatterDelegate, encodeState->classFormatterSelector, object)) == NULL)) ) { goto formatterError; }
2569+
2570+
if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.stringClass)) { isClass = JKClassString; }
2571+
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.numberClass)) { isClass = JKClassNumber; }
2572+
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.dictionaryClass)) { isClass = JKClassDictionary; }
2573+
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.arrayClass)) { isClass = JKClassArray; }
2574+
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.nullClass)) { isClass = JKClassNull; }
2575+
else {
2576+
if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { encodeState->fastClassLookup.stringClass = object->isa; isClass = JKClassString; }
2577+
else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { encodeState->fastClassLookup.numberClass = object->isa; isClass = JKClassNumber; }
2578+
else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { encodeState->fastClassLookup.dictionaryClass = object->isa; isClass = JKClassDictionary; }
2579+
else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { encodeState->fastClassLookup.arrayClass = object->isa; isClass = JKClassArray; }
2580+
else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { encodeState->fastClassLookup.nullClass = object->isa; isClass = JKClassNull; }
2581+
else {
2582+
formatterError:
2583+
if(object == encodeCacheObject) { jk_encode_error(encodeState, @"Unable to serialize object class %@.", NSStringFromClass([encodeCacheObject class])); return(1); }
2584+
else { jk_encode_error(encodeState, @"Unable to serialize object class %@ that was returned by the unsupported class formatter. Original object class was %@.", (object == NULL) ? @"NULL" : NSStringFromClass([object class]), NSStringFromClass([encodeCacheObject class])); return(1); }
2585+
}
2586+
}
2587+
2588+
#endif
25562589
// This is here for the benefit of the optimizer. It allows the optimizer to do loop invariant code motion for the JKClassArray
25572590
// and JKClassDictionary cases when printing simple, single characters via jk_encode_write(), which is actually a macro:
25582591
// #define jk_encode_write1(es, dc, f) (_jk_encode_prettyPrint ? jk_encode_write1slow(es, dc, f) : jk_encode_write1fast(es, dc, f))
@@ -2771,7 +2804,7 @@ - (id)serializeObject:(id)object options:(JKSerializeOptionFlags)optionFlags enc
27712804
id returnObject = NULL;
27722805

27732806
if(encodeState != NULL) { [self releaseState]; }
2774-
if((encodeState = (struct JKEncodeState *)calloc(1UL, sizeof(JKEncodeState))) == NULL) { [NSException exceptionWithName:NSMallocException reason:@"Unable to allocate state structure." userInfo:NULL]; }
2807+
if((encodeState = (struct JKEncodeState *)calloc(1UL, sizeof(JKEncodeState))) == NULL) { [NSException exceptionWithName:NSMallocException reason:@"Unable to allocate state structure." userInfo:NULL]; return(NULL); }
27752808

27762809
if((error != NULL) && (*error != NULL)) { *error = NULL; }
27772810

@@ -2791,7 +2824,7 @@ - (id)serializeObject:(id)object options:(JKSerializeOptionFlags)optionFlags enc
27912824
encodeState->encodeOption = encodeOption;
27922825
encodeState->stringBuffer.roundSizeUpToMultipleOf = (1024UL * 32UL);
27932826
encodeState->utf8ConversionBuffer.roundSizeUpToMultipleOf = 4096UL;
2794-
2827+
27952828
unsigned char stackJSONBuffer[JK_JSONBUFFER_SIZE] JK_ALIGNED(64);
27962829
jk_managedBuffer_setToStackBuffer(&encodeState->stringBuffer, stackJSONBuffer, sizeof(stackJSONBuffer));
27972830

0 commit comments

Comments
 (0)