Adjacent string literals with different encoding prefixes
ID |
objectivec.correctness.mixed_encoding_string_concat |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Literal Format |
Language |
Objective-C |
Description
Reports two adjacent string literals on the same line whose encoding prefixes differ - one of L, u, U or u8 next to a plain literal, an Objective-C literal or a differently prefixed one. Literals that share a prefix, literals separated by a comma or another token, and a prefix appearing inside an escaped quote are not reported.
Rationale
Concatenating literals of different encodings has no defined result in C: an implementation may reject it, or pick one of the two encodings and reinterpret the other literal’s bytes in it. What comes out is a string that is the wrong width or the wrong text, and because the choice is the compiler’s, the same source can behave differently on another toolchain or another platform without any warning at the point of use.
The following code illustrates the pattern detected by this rule:
@implementation Banner
- (void)emit {
// FLAGGED: Adjacent string literals with different encoding prefixes
const wchar_t *title = "Report: " L"summary";
// FLAGGED: Adjacent string literals with different encoding prefixes
const char *utf = u8"café" "-export";
// FLAGGED: Adjacent string literals with different encoding prefixes
const char16_t *wide = u"start" U"end";
// FLAGGED: Adjacent string literals with different encoding prefixes
const char *mixed = L"prefix" u8"suffix";
// FLAGGED: Adjacent string literals with different encoding prefixes
NSString *objc = @"literal" L"wide";
wprintf(L"%ls %s %ls\n", title, utf, wide);
NSLog(@"%@", objc);
}
@end
Remediation
Give both literals the same prefix, so the concatenation is well defined. Where the two really do carry different encodings, keep them as separate values and convert one explicitly at the point they are joined.