Alejandro =?utf-8?q?Álvarez_Ayllón?Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/83...@github.com>
================ @@ -1158,6 +1173,123 @@ void StreamChecker::evalUngetc(const FnDescription *Desc, const CallEvent &Call, C.addTransition(StateFailed); } +ProgramStateRef +StreamChecker::ensurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, + CheckerContext &C, ProgramStateRef State, + const StringRef PtrDescr) const { + const auto Ptr = PtrVal.getAs<DefinedSVal>(); + if (!Ptr) + return nullptr; + + assert(PtrExpr && "Expected an argument"); + + const auto [PtrNotNull, PtrNull] = State->assume(*Ptr); + if (!PtrNotNull && PtrNull) { + if (ExplodedNode *N = C.generateErrorNode(PtrNull)) { + SmallString<256> buf; + llvm::raw_svector_ostream os(buf); + os << PtrDescr << " pointer might be NULL."; + + auto R = std::make_unique<PathSensitiveBugReport>(BT_SizeNull, buf, N); + bugreporter::trackExpressionValue(N, PtrExpr, *R); + C.emitReport(std::move(R)); + } + return nullptr; + } + + return PtrNotNull; +} + +ProgramStateRef StreamChecker::ensureSizeZeroIfLineNull( + SVal LinePtrPtrSVal, SVal SizePtrSVal, const Expr *LinePtrPtrExpr, + const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const { + static constexpr char SizeNotZeroMsg[] = + "Line pointer might be null while n value is not zero"; + + // We have a pointer to a pointer to the buffer, and a pointer to the size. + // We want what they point at. + auto LinePtrSVal = getPointeeDefVal(LinePtrPtrSVal, State); + auto NSVal = getPointeeDefVal(SizePtrSVal, State); + if (!LinePtrSVal || !NSVal) + return nullptr; + + assert(LinePtrPtrExpr && + "Expected an argument with a pointer to a pointer to the buffer."); + assert(SizePtrExpr && + "Expected an argument with a pointer to the buffer size."); + + // If the line pointer is null, and n is > 0, there is UB. + const auto [LinePtrNotNull, LinePtrNull] = State->assume(*LinePtrSVal); + if (LinePtrNull && !LinePtrNotNull) { + const auto [NIsNotZero, NIsZero] = LinePtrNull->assume(*NSVal); + if (NIsNotZero && !NIsZero) { + if (ExplodedNode *N = C.generateErrorNode(NIsNotZero)) { + auto R = std::make_unique<PathSensitiveBugReport>(BT_SizeNotZero, + SizeNotZeroMsg, N); + bugreporter::trackExpressionValue(N, SizePtrExpr, *R); + bugreporter::trackExpressionValue(N, LinePtrPtrExpr, *R); + C.emitReport(std::move(R)); + } + return nullptr; + } + return NIsZero; + } + return LinePtrNotNull; +} + +void StreamChecker::preGetdelim(const FnDescription *Desc, + const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + SVal StreamVal = getStreamArg(Desc, Call); + + auto AddTransitionOnReturn = llvm::make_scope_exit([&] { + if (State != nullptr) { + C.addTransition(State); + } + }); + + State = ensureStreamNonNull(StreamVal, Call.getArgExpr(Desc->StreamArgNo), C, + State); + if (!State) + return; + State = ensureStreamOpened(StreamVal, C, State); + if (!State) + return; + State = ensureNoFilePositionIndeterminate(StreamVal, C, State); + if (!State) + return; + + // The parameter `n` must not be NULL. + SVal SizePtrSval = Call.getArgSVal(1); + State = ensurePtrNotNull(SizePtrSval, Call.getArgExpr(1), C, State, "Size"); + if (!State) + return; + + // The parameter `lineptr` must not be NULL. + SVal LinePtrPtrSVal = Call.getArgSVal(0); + State = + ensurePtrNotNull(LinePtrPtrSVal, Call.getArgExpr(0), C, State, "Line"); + if (!State) + return; + + // If `lineptr` points to a NULL pointer, `*n` must be 0. + State = + ensureSizeZeroIfLineNull(LinePtrPtrSVal, SizePtrSval, Call.getArgExpr(0), + Call.getArgExpr(1), C, State); + if (!State) + return; + + SymbolRef Sym = StreamVal.getAsSymbol(); + if (Sym && State->get<StreamMap>(Sym)) { + const StreamState *SS = State->get<StreamMap>(Sym); + if (SS->ErrorState & ErrorFEof) + reportFEofWarning(Sym, C, State); + } else { + C.addTransition(State); + } ---------------- steakhal wrote: ```suggestion } ``` You add this transition anyways via the scope_exit. https://github.com/llvm/llvm-project/pull/83027 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits