diff --git a/infer/models/objc/src/NSString.h b/infer/models/objc/src/NSString.h index 290ddb849..fc2fbb1ae 100644 --- a/infer/models/objc/src/NSString.h +++ b/infer/models/objc/src/NSString.h @@ -17,5 +17,6 @@ + (instancetype)localizedStringWithFormat:(NSString*)format, ...; - (instancetype)initWithFormat:(NSString*)format, ...; - (instancetype)initWithFormat:(NSString*)format arguments:(va_list)argList; +- (instancetype)stringByAppendingString:(NSString*)aString; - (void)dealloc; @end diff --git a/infer/models/objc/src/NSString.m b/infer/models/objc/src/NSString.m index 3b0b0dcea..a50d67315 100644 --- a/infer/models/objc/src/NSString.m +++ b/infer/models/objc/src/NSString.m @@ -82,6 +82,11 @@ typedef NSUInteger NSStringEncoding; } } +- (instancetype)stringByAppendingString:(NSString*)aString { + const char* v = aString->value; + return self; +} + - (void)dealloc { if (self != nil && self->value != 0) { free((void*)self->value); diff --git a/infer/tests/codetoanalyze/objc/errors/Makefile b/infer/tests/codetoanalyze/objc/errors/Makefile index fb8d266ca..c94b72bb6 100644 --- a/infer/tests/codetoanalyze/objc/errors/Makefile +++ b/infer/tests/codetoanalyze/objc/errors/Makefile @@ -30,6 +30,7 @@ SOURCES_DEFAULT = \ npe/ivar_blocks.m \ npe/skip_method_with_nil_object.m \ npe/Nsstring_length_no_npe.m \ + npe/Nsstring_nil_args.m \ npe/No_null_from_array.m \ procdescs/MethodCall.m \ property/main.c \ diff --git a/infer/tests/codetoanalyze/objc/errors/issues.exp b/infer/tests/codetoanalyze/objc/errors/issues.exp index c6945b603..c83e8a951 100644 --- a/infer/tests/codetoanalyze/objc/errors/issues.exp +++ b/infer/tests/codetoanalyze/objc/errors/issues.exp @@ -78,6 +78,10 @@ codetoanalyze/objc/errors/memory_leaks_benchmark/NSString_models_tests.m, String codetoanalyze/objc/errors/memory_leaks_benchmark/RetainCycleLength3.m, strongcycle, 6, RETAIN_CYCLE, no_bucket, ERROR, [start of procedure strongcycle(),Executing synthesized setter setB:,Executing synthesized setter setC:,Executing synthesized setter setA:] codetoanalyze/objc/errors/npe/Fraction.m, test_virtual_call, 7, NULL_DEREFERENCE, B1, ERROR, [start of procedure test_virtual_call(),start of procedure setNumerator:,return from a call to Fraction_setNumerator:,start of procedure getNumerator,return from a call to Fraction_getNumerator,Taking true branch] codetoanalyze/objc/errors/npe/Npe_with_equal_names.m, EqualNamesTest, 3, NULL_DEREFERENCE, B1, ERROR, [start of procedure EqualNamesTest(),start of procedure meth,return from a call to EqualNamesA_meth] +codetoanalyze/objc/errors/npe/Nsstring_nil_args.m, initWithFormatBad, 3, NULL_DEREFERENCE, B1, ERROR, [start of procedure initWithFormatBad()] +codetoanalyze/objc/errors/npe/Nsstring_nil_args.m, stringByAppendingStringBad, 2, NULL_DEREFERENCE, B1, ERROR, [start of procedure stringByAppendingStringBad()] +codetoanalyze/objc/errors/npe/Nsstring_nil_args.m, stringWithStringBad, 2, NULL_DEREFERENCE, B1, ERROR, [start of procedure stringWithStringBad(),start of procedure nullableMethod(),return from a call to nullableMethod] +codetoanalyze/objc/errors/npe/Nsstring_nil_args.m, stringWithUTF8StringBad, 1, NULL_DEREFERENCE, B5, ERROR, [start of procedure stringWithUTF8StringBad(),start of procedure nullableMethod(),return from a call to nullableMethod] codetoanalyze/objc/errors/npe/block.m, BlockA_doSomethingThenCallback:, 2, PARAMETER_NOT_NULL_CHECKED, B1, WARNING, [start of procedure doSomethingThenCallback:] codetoanalyze/objc/errors/npe/block.m, BlockA_foo, 5, NULL_DEREFERENCE, B1, ERROR, [start of procedure foo] codetoanalyze/objc/errors/npe/block.m, BlockA_foo3:, 3, NULL_DEREFERENCE, B1, ERROR, [start of procedure foo3:] diff --git a/infer/tests/codetoanalyze/objc/errors/npe/Nsstring_nil_args.m b/infer/tests/codetoanalyze/objc/errors/npe/Nsstring_nil_args.m new file mode 100644 index 000000000..a2a083406 --- /dev/null +++ b/infer/tests/codetoanalyze/objc/errors/npe/Nsstring_nil_args.m @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NSString* nullableMethod() { return nil; } + +NSString* stringWithUTF8StringGood() { + NSString* str = [NSString stringWithUTF8String:"a"]; + return str; +} + +NSString* stringWithUTF8StringBad() { + NSString* str = [NSString stringWithUTF8String:nullableMethod()]; + return str; +} + +NSString* stringWithStringGood() { + NSString* str = [NSString stringWithString:@"a"]; + return str; +} + +NSString* stringWithStringBad() { + NSString* s = nullableMethod(); + NSString* str = [NSString stringWithString:s]; + return str; +} + +NSString* initWithFormatGood() { + NSString* str = @"a"; + [str initWithFormat:@"a"]; + return str; +} + +NSString* initWithFormatBad() { + NSString* str = @"a"; + NSString* fmt = nil; + [str initWithFormat:fmt]; + return str; +} + +NSString* stringByAppendingStringGood() { + NSString* str = @"a"; + [str stringByAppendingString:@"b"]; + return str; +} + +NSString* stringByAppendingStringBad() { + NSString* str = @"a"; + [str stringByAppendingString:nil]; + return str; +}