This is an archive of the discontinued LLVM Phabricator instance.

[llvm][ProfileData] Add a warning to indicate potentially corrupted data
Needs ReviewPublic

Authored by leonardchan on Aug 25 2021, 8:40 PM.

Details

Summary

This is meant to address PR51628 where we hit an OOM error when accidentally uncompressing corrupted raw profile data. Ideally, there would be some warning or indicator of why this occurred rather than just failing with OOM.

Diff Detail

Event Timeline

leonardchan created this revision.Aug 25 2021, 8:40 PM
leonardchan requested review of this revision.EditedAug 25 2021, 8:40 PM

I'm not particularly fond of this solution, but I couldn't think of anything better (and am open for suggestions). My initial thought was that we could instead use a char * for the buffer rather than a SmallString, and when allocating the buffer we could just check if the malloc for the UncompressedSize failed or not (nullptr could indicate either corrupt value or just not enough memory). But we'd still run into the LLVM ERROR on the malloc since LLVM would still catch the error (via signal handlers) and do the normal error reporting.

Additionally, I couldn't find other ways we could "validate" the uncompressed size. That is, I don't *think* there is any absolute way of determining if the uncompressed size is corrupted data or the uncompressed size is just really large.

Is OOM worth avoiding? Presumably some real-world cases could exceed the limits of a given machine anyway, right? (I'm not sure that LLVM and Clang avoid OOM, for instance - you can probably make some Clang AST that can't be stored in the memory available on some systems)

I think this warning is not about OOM, but corrupted profile data. Regular OOM may not worth warning.

What's the nature of the corruption?
I'd probably prefer to avoid heuristics like the one suggested here. Is there something in the uncompressed data that is certainly wrong in this case?

It seems that the uncompressed size field is corrupted and becomes too large. The warning seems just catching this quite narrow case.

The definition of "too large" seems heuristical though - it's not provably wrong, just unlikely/'weird'. It's possible a legitimate use could have such a value - and the right answer would be to OOM, basically?

I guess I don't mind it too much as a warning, at least. Doesn't block it from working if there's a legitimate input that happens to compress well.

The intent is to sanity-check for garbage header fields. The uncompressed size field is one that you can only warn about heuristically like this I guess. But you can do a definitive test on the CompressedSize field to ensure that it isn't larger than the actual size of the data available. There's no need to even worry about whether UncompressedSize is valid if CompressedSize is clearly invalid.

Since these fields come from the binary and should be identical (profile runtime simply copies them into the raw profile), a different approach would be to have a new subcommand in llvm-profdata to validate the profile against the binary to check if those fields are indeed the same, for example something like llvm-profdata validate --object=<binary> <profile>.profraw (alternatively it could also be just a flag, for example llvm-profdata merge --validate=<binary> <profile>.profraw).

Both Roland and Petr's suggestions are great.

gulfem added a subscriber: gulfem.Sep 7 2021, 10:05 AM