[PATCH v3] Bug 14526 - Make malloc() static analysis M_ZERO-aware
Jordan Rose
jordan_rose at apple.com
Fri Mar 21 10:37:39 PDT 2014
On Mar 21, 2014, at 10:25, Meyer, Conrad <conrad.meyer at isilon.com> wrote:
> On Fri, Mar 21, 2014 at 1:11 PM, Jordan Rose <jordan_rose at apple.com> wrote:
>>
>> On Mar 20, 2014, at 6:08 , Meyer, Conrad <conrad.meyer at isilon.com> wrote:
>>
>>> + mutable Optional<uint64_t> Val_M_ZERO;
>>
>> Let's rename this something generic, like KernelZeroFlagVal;
>>
>
> Easy to do.
>
>>
>>>
>>> void initIdentifierInfo(ASTContext &C) const;
>>>
>>> /// \brief Determine family of a deallocation expression.
>>> AllocationFamily getAllocationFamily(CheckerContext &C, const Stmt *S) const;
>>> @@ -251,10 +255,15 @@ private:
>>> static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
>>> SVal SizeEx, SVal Init,
>>> ProgramStateRef State,
>>> AllocationFamily Family = AF_Malloc);
>>>
>>> + // Check if this malloc() uses M_ZERO or __GFP_ZERO (treat like calloc).
>>> + llvm::Optional<ProgramStateRef>
>>> + MallocZero(const CallExpr *CE, CheckerContext &C,
>>> + const ProgramStateRef &State) const;
>>> +
>>
>> How about something like "performKernelMalloc"? The special thing here is that it handles the two- and three-argument forms if it knows how. We may want to add support for the other flags some day.
>
> Sure.
>
>>
>> Are there ever going to be systems that have both kmalloc and malloc-with-flags?
>
> BSD has a Linux kernel compatibility layer for some dual-licensed drivers ("OFED," I think, and possibly others). And I wouldn't be surprised to see the opposite direction either. So while I don't *know* that such a system exists, it wouldn't be super surprising either.
>
>>>
>>> +llvm::Optional<ProgramStateRef> MallocChecker::MallocZero(const CallExpr *CE,
>>> + CheckerContext &C, const ProgramStateRef &State) const {
>>> + // 3-argument malloc(), as commonly used in {Free,Net,Open}BSD Kernels:
>>> + //
>>> + // void *malloc(unsigned long size, struct malloc_type *mtp, int flags);
>>> + //
>>> + // One of the possible flags is M_ZERO, which means 'give me back an
>>> + // allocation which is already zeroed', like calloc.
>>> +
>>> + // 2-argument kmalloc(), as used in the Linux kernel:
>>> + //
>>> + // void *kmalloc(size_t size, gfp_t flags);
>>> + //
>>> + // Has the similar flag value __GFP_ZERO.
>>> +
>>> + // This logic is largely cloned from O_CREAT in UnixAPIChecker, maybe some
>>> + // code could be shared.
>>> +
>>> + llvm::Triple::OSType os = C.getASTContext().getTargetInfo().getTriple().getOS();
>>> + llvm::Optional<ProgramStateRef> RetVal;
>>> +
>>> + if (!Val_M_ZERO.hasValue()) {
>>> + if (os == llvm::Triple::FreeBSD)
>>> + Val_M_ZERO = 0x0100;
>>> + else if (os == llvm::Triple::NetBSD)
>>> + Val_M_ZERO = 0x0002;
>>> + else if (os == llvm::Triple::OpenBSD)
>>> + Val_M_ZERO = 0x0008;
>>> + else if (os == llvm::Triple::Linux)
>>> + // __GFP_ZERO
>>> + Val_M_ZERO = 0x8000;
>>> + else
>>> + // FIXME: We need a more general way of getting the M_ZERO value.
>>> + // See also: O_CREAT in UnixAPIChecker.cpp.
>>> +
>>> + // Fall back to normal malloc behavior on platforms where we don't
>>> + // know M_ZERO.
>>> + return RetVal;
>>
>> This can be written "return None;". "None" implicitly converts to an empty Optional.
>
> Is None a special global or #define in LLVM/Clang? I haven't heard of it in C++ before. But that's easy enough to change.
Check out clang/Basic/LLVM.h, llvm/ADT/None.h, and llvm/ADT/Optional.h. It's special, but just using the rules of C++ to do what we want.
Jordan
More information about the cfe-commits
mailing list