This is an archive of the discontinued LLVM Phabricator instance.

[scudo] Change aligned alloc functions to be more compliant & perf changes
ClosedPublic

Authored by cryptoad on Jun 28 2017, 2:37 PM.

Details

Summary

We were not following the man documented behaviors for invalid arguments to
memalign and associated functions. Using CHECK for those was a bit extreme,
so we relax the behavior to return null pointers as expected when this happens.
Adapt the associated test.

I am using this change also to change a few more minor performance improvements:

  • mark as UNLIKELY a bunch of unlikely conditions;
  • the current CHECK in __sanitizer::RoundUpTo is redundant for us in *all* calls. So I am introducing our own version without said CHECK.
  • change our combined allocator GetActuallyAllocatedSize. We already know if the pointer is from the Primary or Secondary, so the PointerIsMine check is redundant as well, and costly for the 32-bit Primary. So we get the size by directly using the available Primary functions.

Finally, change a int to uptr to avoid a warning/error when compiling on
Android.

Event Timeline

cryptoad created this revision.Jun 28 2017, 2:37 PM
cryptoad updated this revision to Diff 104516.Jun 28 2017, 2:39 PM

Removing the CHECK line in the test that is no longer needed.

alekseyshl added inline comments.Jun 28 2017, 4:42 PM
lib/scudo/scudo_allocator.cpp
346

Why this one is likely? My guess would be that most pointers we get to check are valid. Is it not so?

583–584

Others use CallocShouldReturnNullDueToOverflow, maybe you can use it too?

666

Why nullptr, why not return FailureHandler::OnBadRequest()?

672

Same here

683

And here

lib/scudo/scudo_allocator.h
119

Please add a comment why you have your own RoundUpTo, otherwise someone later will "improve" the code back.

cryptoad added inline comments.Jun 28 2017, 6:19 PM
lib/scudo/scudo_allocator.cpp
346

So on this, I went back and forth. Basically this is a helper function that is only used for __sanitizer_get_ownership.
I assume that anything can be fed to this function, as opposed to only heap pointers.
The reasoning was that nullptr was less likely overall, but then I have no guarantee on alignments.

583–584

Good point. Will do.

666

Here and for the following comments, I guess my answer (which is debatable) is that it's not technically a bad request.
The man page for memalign, posix_memalign, and aligned_alloc says that hey return null for those specific cases.
Which, in my opinion, is different that trying to exceed a maximum alignment or size, or triggering an overflow in calloc.
As such I would lean towards this behavior as opposed to a failure or null based on an allocator setting.
Let me know if that makes sense.
If you judge that OnBadRequest is the way to go, I'll go that way, I am not strongly attached to the way I did it.

lib/scudo/scudo_allocator.h
119

Will do.

alekseyshl added inline comments.Jun 28 2017, 6:56 PM
lib/scudo/scudo_allocator.cpp
346

Makes sense.

583–584

D34799 renames it to CheckForCallocOverflow. Whoever is late to commit, gets to merge, I guess :)

666

My take on it is that we have a flag allocator_may_return_null and when it is == 0, our allocator should do just that, never return null. If the client desires the up to the spec behavior of those memory functions, they should specify allocator_may_return_null=1.

That way our behavior is consistent.

I'm open to debate too, there's always some space for improvements!

675–677

To follow the spec, we should check the result too:

if (!*MemPtr)

return errno_ENOMEM;
cryptoad added inline comments.Jun 28 2017, 7:30 PM
lib/scudo/scudo_allocator.cpp
666

I'll revisit that portion tomorrow and see how it checks out.

675–677

Yeah I wanted to talk to you about that.
Following what's in https://linux.die.net/man/3/malloc (look for ENOMEM) , we should probably set the errno in ReturnNullOrDieOnFailure::OnOOM (or whichever works better).

cryptoad added inline comments.Jun 29 2017, 8:32 AM
lib/scudo/scudo_allocator.cpp
675–677

I just realized there is no errno_ENOMEM. Do you know the reasoning behind having errno_E* as opposed to using the E* value itself?

alekseyshl added inline comments.Jun 29 2017, 8:59 AM
lib/scudo/scudo_allocator.cpp
675–677

Nope, I do not know the reason, and yes, you're right, we must set errno to ENOMEM in case of OOM (Windows expects the same, actually).

cryptoad updated this revision to Diff 104668.Jun 29 2017, 9:34 AM
cryptoad marked 18 inline comments as done.

Addressing the review comments.
I will wait for D34799 to land anyway due to the switch to CheckForCallocOverflow.

alekseyshl accepted this revision.Jun 29 2017, 9:41 AM

Or just go ahead and submit it, I'll merge with your changes.

This revision is now accepted and ready to land.Jun 29 2017, 9:41 AM
cryptoad closed this revision.Jun 29 2017, 9:45 AM