diff --git a/infer/models/objc/src/NSNumber.m b/infer/models/objc/src/NSNumber.m index 476de3f22..cbc8837cb 100644 --- a/infer/models/objc/src/NSNumber.m +++ b/infer/models/objc/src/NSNumber.m @@ -55,4 +55,14 @@ return self; } +- (id)initWithUnsignedInteger:(NSUInteger)v { + self->value = v; + return self; +} + ++ (NSNumber*)numberWithUnsignedInteger:(NSUInteger)value { + NSNumber* number = [self alloc]; + return [number initWithUnsignedInteger:value]; +} + @end diff --git a/infer/tests/codetoanalyze/objc/errors/npe/BoxedNumberExample.m b/infer/tests/codetoanalyze/objc/errors/npe/BoxedNumberExample.m new file mode 100644 index 000000000..fc636cd3e --- /dev/null +++ b/infer/tests/codetoanalyze/objc/errors/npe/BoxedNumberExample.m @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#include + +typedef NS_ENUM(NSUInteger, SpacingEnum) { + SpacingFill, + SpacingCenter, + SpacingLeading, + SpacingTrailing, +}; + +@interface A : NSObject + +@end + +@implementation A { + NSMutableDictionary* _spacingMap; +} + +- (void)setMinimumHorizontalPadding:(SpacingEnum)horizontalSpacing + and:(SpacingEnum)spacingValue { + NSNumber* key = @(horizontalSpacing); + NSNumber* value = @(spacingValue); + if ((_spacingMap[key] != value)) { + _spacingMap[key] = value; + } +} + +@end diff --git a/infer/tests/endtoend/objc/BoxedNumberNoNPETest.java b/infer/tests/endtoend/objc/BoxedNumberNoNPETest.java new file mode 100644 index 000000000..3cb48a0de --- /dev/null +++ b/infer/tests/endtoend/objc/BoxedNumberNoNPETest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package endtoend.objc; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.ResultContainsExactly.containsExactly; + +import com.google.common.collect.ImmutableList; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.IOException; + +import utils.DebuggableTemporaryFolder; +import utils.InferException; +import utils.InferResults; +import utils.InferRunner; + +public class BoxedNumberNoNPETest { + + public static final String FILE = + "infer/tests/codetoanalyze/objc/errors/npe/BoxedNumberExample.m"; + + private static ImmutableList inferCmd; + + public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE"; + + @ClassRule + public static DebuggableTemporaryFolder folder = + new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createiOSInferCommandWithMLBuckets( + folder, + FILE, + "cf", + true); + } + + @Test + public void whenInferRunsOnBoxedExampleNoNPEIsFound() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferC(inferCmd); + String[] procedures = { + }; + assertThat( + "Results should contain no " + NULL_DEREFERENCE, + inferResults, + containsExactly( + NULL_DEREFERENCE, + FILE, + procedures + ) + ); + } +}