Skip to content

Commit 7f25a88

Browse files
committed
[analyzer] Remove rdar links from static analyzer and libAnalysis sources. NFC.
I actually visited each link and added relevant context directly to the code. This is related to the effort to eliminate internal bug tracker links (d618f1c, e0ac46e). Test files still have a lot of rdar links and ids in them. I haven't touched them yet.
1 parent 38b648b commit 7f25a88

File tree

6 files changed

+70
-58
lines changed

6 files changed

+70
-58
lines changed

clang/lib/Analysis/CFG.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,8 +2224,7 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
22242224
// FIXME: The expression inside a CXXDefaultArgExpr is owned by the
22252225
// called function's declaration, not by the caller. If we simply add
22262226
// this expression to the CFG, we could end up with the same Expr
2227-
// appearing multiple times.
2228-
// PR13385 / <rdar://problem/12156507>
2227+
// appearing multiple times (PR13385).
22292228
//
22302229
// It's likewise possible for multiple CXXDefaultInitExprs for the same
22312230
// expression to be used in the same function (through aggregate

clang/lib/Analysis/RetainSummaryManager.cpp

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,9 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
301301

302302
std::string RetTyName = RetTy.getAsString();
303303
if (FName == "pthread_create" || FName == "pthread_setspecific") {
304-
// Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
305-
// This will be addressed better with IPA.
304+
// It's not uncommon to pass a tracked object into the thread
305+
// as 'void *arg', and then release it inside the thread.
306+
// FIXME: We could build a much more precise model for these functions.
306307
return getPersistentStopSummary();
307308
} else if(FName == "NSMakeCollectable") {
308309
// Handle: id NSMakeCollectable(CFTypeRef)
@@ -311,7 +312,8 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
311312
: getPersistentStopSummary();
312313
} else if (FName == "CMBufferQueueDequeueAndRetain" ||
313314
FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
314-
// Part of: <rdar://problem/39390714>.
315+
// These API functions are known to NOT act as a CFRetain wrapper.
316+
// They simply make a new object owned by the caller.
315317
return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
316318
ScratchArgs,
317319
ArgEffect(DoNothing),
@@ -324,52 +326,47 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
324326
FName == "IOServiceNameMatching" ||
325327
FName == "IORegistryEntryIDMatching" ||
326328
FName == "IOOpenFirmwarePathMatching"))) {
327-
// Part of <rdar://problem/6961230>. (IOKit)
328-
// This should be addressed using a API table.
329+
// Yes, these IOKit functions return CF objects.
330+
// They also violate the CF naming convention.
329331
return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
330332
ArgEffect(DoNothing), ArgEffect(DoNothing));
331333
} else if (FName == "IOServiceGetMatchingService" ||
332334
FName == "IOServiceGetMatchingServices") {
333-
// FIXES: <rdar://problem/6326900>
334-
// This should be addressed using a API table. This strcmp is also
335-
// a little gross, but there is no need to super optimize here.
335+
// These IOKit functions accept CF objects as arguments.
336+
// They also consume them without an appropriate annotation.
336337
ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF));
337338
return getPersistentSummary(RetEffect::MakeNoRet(),
338339
ScratchArgs,
339340
ArgEffect(DoNothing), ArgEffect(DoNothing));
340341
} else if (FName == "IOServiceAddNotification" ||
341342
FName == "IOServiceAddMatchingNotification") {
342-
// Part of <rdar://problem/6961230>. (IOKit)
343-
// This should be addressed using a API table.
343+
// More IOKit functions suddenly accepting (and even more suddenly,
344+
// consuming) CF objects.
344345
ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF));
345346
return getPersistentSummary(RetEffect::MakeNoRet(),
346347
ScratchArgs,
347348
ArgEffect(DoNothing), ArgEffect(DoNothing));
348349
} else if (FName == "CVPixelBufferCreateWithBytes") {
349-
// FIXES: <rdar://problem/7283567>
350350
// Eventually this can be improved by recognizing that the pixel
351351
// buffer passed to CVPixelBufferCreateWithBytes is released via
352352
// a callback and doing full IPA to make sure this is done correctly.
353-
// FIXME: This function has an out parameter that returns an
353+
// Note that it's passed as a 'void *', so it's hard to annotate.
354+
// FIXME: This function also has an out parameter that returns an
354355
// allocated object.
355356
ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking));
356357
return getPersistentSummary(RetEffect::MakeNoRet(),
357358
ScratchArgs,
358359
ArgEffect(DoNothing), ArgEffect(DoNothing));
359360
} else if (FName == "CGBitmapContextCreateWithData") {
360-
// FIXES: <rdar://problem/7358899>
361+
// This is similar to the CVPixelBufferCreateWithBytes situation above.
361362
// Eventually this can be improved by recognizing that 'releaseInfo'
362363
// passed to CGBitmapContextCreateWithData is released via
363364
// a callback and doing full IPA to make sure this is done correctly.
364365
ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking)));
365366
return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
366367
ArgEffect(DoNothing), ArgEffect(DoNothing));
367368
} else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
368-
// FIXES: <rdar://problem/7283567>
369-
// Eventually this can be improved by recognizing that the pixel
370-
// buffer passed to CVPixelBufferCreateWithPlanarBytes is released
371-
// via a callback and doing full IPA to make sure this is done
372-
// correctly.
369+
// Same as CVPixelBufferCreateWithBytes, just more arguments.
373370
ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking));
374371
return getPersistentSummary(RetEffect::MakeNoRet(),
375372
ScratchArgs,
@@ -386,12 +383,10 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
386383
ArgEffect(DoNothing), ArgEffect(DoNothing));
387384
} else if (FName == "dispatch_set_context" ||
388385
FName == "xpc_connection_set_context") {
389-
// <rdar://problem/11059275> - The analyzer currently doesn't have
390-
// a good way to reason about the finalizer function for libdispatch.
386+
// The analyzer currently doesn't have a good way to reason about
387+
// dispatch_set_finalizer_f() which typically cleans up the context.
391388
// If we pass a context object that is memory managed, stop tracking it.
392-
// <rdar://problem/13783514> - Same problem, but for XPC.
393-
// FIXME: this hack should possibly go away once we can handle
394-
// libdispatch and XPC finalizers.
389+
// Same with xpc_connection_set_finalizer_f().
395390
ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
396391
return getPersistentSummary(RetEffect::MakeNoRet(),
397392
ScratchArgs,
@@ -740,8 +735,8 @@ RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD,
740735
// It's okay to be a little sloppy here.
741736
if (FName == "CMBufferQueueDequeueAndRetain" ||
742737
FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
743-
// Part of: <rdar://problem/39390714>.
744-
// These are not retain. They just return something and retain it.
738+
// These API functions are known to NOT act as a CFRetain wrapper.
739+
// They simply make a new object owned by the caller.
745740
return std::nullopt;
746741
}
747742
if (CE->getNumArgs() == 1 &&
@@ -1243,8 +1238,6 @@ void RetainSummaryManager::InitializeMethodSummaries() {
12431238
// FIXME: For now we opt for false negatives with NSWindow, as these objects
12441239
// self-own themselves. However, they only do this once they are displayed.
12451240
// Thus, we need to track an NSWindow's display status.
1246-
// This is tracked in <rdar://problem/6062711>.
1247-
// See also http://llvm.org/bugs/show_bug.cgi?id=3714.
12481241
const RetainSummary *NoTrackYet =
12491242
getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
12501243
ArgEffect(StopTracking), ArgEffect(StopTracking));
@@ -1259,7 +1252,6 @@ void RetainSummaryManager::InitializeMethodSummaries() {
12591252

12601253
// For NSNull, objects returned by +null are singletons that ignore
12611254
// retain/release semantics. Just don't track them.
1262-
// <rdar://problem/12858915>
12631255
addClassMethSummary("NSNull", "null", NoTrackYet);
12641256

12651257
// Don't track allocated autorelease pools, as it is okay to prematurely

clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ void WalkAST::VisitForStmt(ForStmt *FS) {
219219

220220
//===----------------------------------------------------------------------===//
221221
// Check: floating point variable used as loop counter.
222-
// Originally: <rdar://problem/6336718>
223222
// Implements: CERT security coding advisory FLP-30.
224223
//===----------------------------------------------------------------------===//
225224

@@ -467,8 +466,8 @@ void WalkAST::checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD) {
467466

468467

469468
//===----------------------------------------------------------------------===//
470-
// Check: Any use of 'gets' is insecure.
471-
// Originally: <rdar://problem/6335715>
469+
// Check: Any use of 'gets' is insecure. Most man pages literally says this.
470+
//
472471
// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
473472
// CWE-242: Use of Inherently Dangerous Function
474473
//===----------------------------------------------------------------------===//
@@ -847,8 +846,13 @@ bool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) {
847846
}
848847

849848
//===----------------------------------------------------------------------===//
850-
// Check: Linear congruent random number generators should not be used
851-
// Originally: <rdar://problem/63371000>
849+
// Check: Linear congruent random number generators should not be used,
850+
// i.e. rand(), random().
851+
//
852+
// E. Bach, "Efficient prediction of Marsaglia-Zaman random number generators,"
853+
// in IEEE Transactions on Information Theory, vol. 44, no. 3, pp. 1253-1257,
854+
// May 1998, https://doi.org/10.1109/18.669305
855+
//
852856
// CWE-338: Use of cryptographically weak prng
853857
//===----------------------------------------------------------------------===//
854858

@@ -890,11 +894,7 @@ void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
890894
CE->getCallee()->getSourceRange());
891895
}
892896

893-
//===----------------------------------------------------------------------===//
894-
// Check: 'random' should not be used
895-
// Originally: <rdar://problem/63371000>
896-
//===----------------------------------------------------------------------===//
897-
897+
// See justification for rand().
898898
void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
899899
if (!CheckRand || !filter.check_rand)
900900
return;
@@ -990,8 +990,18 @@ void WalkAST::checkMsg_decodeValueOfObjCType(const ObjCMessageExpr *ME) {
990990
}
991991

992992
//===----------------------------------------------------------------------===//
993-
// Check: Should check whether privileges are dropped successfully.
994-
// Originally: <rdar://problem/6337132>
993+
// Check: The caller should always verify that the privileges
994+
// were dropped successfully.
995+
//
996+
// Some library functions, like setuid() and setgid(), should always be used
997+
// with a check of the return value to verify that the function completed
998+
// successfully. If the drop fails, the software will continue to run
999+
// with the raised privileges, which might provide additional access
1000+
// to unprivileged users.
1001+
//
1002+
// (Note that this check predates __attribute__((warn_unused_result)).
1003+
// Do we still need it now that we have a compiler warning for this?
1004+
// Are these standard functions already annotated this way?)
9951005
//===----------------------------------------------------------------------===//
9961006

9971007
void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {

clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,6 @@ RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
786786
assert(RV);
787787

788788
if (RV->getKind() == RefVal::ErrorLeakReturned) {
789-
// FIXME: Per comments in rdar://6320065, "create" only applies to CF
790-
// objects. Only "copy", "alloc", "retain" and "new" transfer ownership
791-
// to the caller for NS objects.
792789
const Decl *D = &EndN->getCodeDecl();
793790

794791
os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "

clang/lib/StaticAnalyzer/Core/CallEvent.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,8 +765,9 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
765765
// the static type. However, because we currently don't update
766766
// DynamicTypeInfo when an object is cast, we can't actually be sure the
767767
// DynamicTypeInfo is up to date. This assert should be re-enabled once
768-
// this is fixed. <rdar://problem/12287087>
769-
//assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo");
768+
// this is fixed.
769+
//
770+
// assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo");
770771

771772
return {};
772773
}

clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,19 +167,32 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
167167
// intentionally drops coverage in order to prevent false alarms
168168
// in the following scenario:
169169
//
170-
// id result = [o someMethod]
171-
// if (result) {
172-
// if (!o) {
173-
// // <-- This program point should be unreachable because if o is nil
174-
// // it must the case that result is nil as well.
170+
// id result = [o someMethod]
171+
// if (result) {
172+
// if (!o) {
173+
// // <-- This program point should be unreachable because if o is nil
174+
// // it must the case that result is nil as well.
175+
// }
175176
// }
176-
// }
177177
//
178-
// We could avoid dropping coverage by performing an explicit case split
179-
// on each method call -- but this would get very expensive. An alternative
180-
// would be to introduce lazy constraints.
181-
// FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
182-
// Revisit once we have lazier constraints.
178+
// However, it also loses coverage of the nil path prematurely,
179+
// leading to missed reports.
180+
//
181+
// It's possible to handle this by performing a state split on every call:
182+
// explore the state where the receiver is non-nil, and independently
183+
// explore the state where it's nil. But this is not only slow, but
184+
// completely unwarranted. The mere presence of the message syntax in the code
185+
// isn't sufficient evidence that nil is a realistic possibility.
186+
//
187+
// An ideal solution would be to add the following constraint that captures
188+
// both possibilities without splitting the state:
189+
//
190+
// ($x == 0) => ($y == 0) (1)
191+
//
192+
// where in our case '$x' is the receiver symbol, '$y' is the returned symbol,
193+
// and '=>' is logical implication. But RangeConstraintManager can't handle
194+
// such constraints yet, so for now we go with a simpler, more restrictive
195+
// constraint: $x != 0, from which (1) follows as a vacuous truth.
183196
if (Msg->isInstanceMessage()) {
184197
SVal recVal = Msg->getReceiverSVal();
185198
if (!recVal.isUndef()) {

0 commit comments

Comments
 (0)