-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vec: with_capacity: check for overflow #10417
Conversation
let alloc = capacity * mem::nonzero_size_of::<T>(); | ||
let ptr = malloc_raw(alloc + mem::size_of::<Vec<()>>()) as *mut Vec<()>; | ||
let alloc = capacity.checked_mul(&mem::nonzero_size_of::<T>()) | ||
.expect("with_capacity: vector size overflowed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a failure, or an abort? (Also, does the managed branch need checks too?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reserve doesn't need checks, see line 1414. reserve_raw in at_vec also checks for overflow.
@@ -186,7 +186,11 @@ pub fn with_capacity<T>(capacity: uint) -> ~[T] { | |||
vec | |||
} else { | |||
let alloc = capacity * mem::nonzero_size_of::<T>(); | |||
let ptr = malloc_raw(alloc + mem::size_of::<Vec<()>>()) as *mut Vec<()>; | |||
let size = alloc + mem::size_of::<Vec<()>>(); | |||
if alloc / mem::nonzero_size_of::<T>() != capacity || size < alloc { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this check incorrect, because the header is included in alloc
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. The header comes from size_of::<Vec<()>>. This is the same code used
for overflow handling elsewhere. cc @thestinger
On Mon, Nov 11, 2013 at 6:23 AM, Huon Wilson notifications@gh.neting.ccwrote:
In src/libstd/vec.rs:
@@ -186,7 +186,11 @@ pub fn with_capacity(capacity: uint) -> ~[T] {
vec
} else {
let alloc = capacity * mem::nonzero_size_of::();
let ptr = malloc_raw(alloc + mem::size_of::<Vec<()>>()) as *mut Vec<()>;
let size = alloc + mem::size_of::<Vec<()>>();
if alloc / mem::nonzero_size_of::<T>() != capacity || size < alloc {
Isn't this check incorrect, because the header is included in alloc?
—
Reply to this email directly or view it on GitHubhttps://github.com//pull/10417/files#r7556668
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, of course... it's alloc / ...
not size / ...
.
@cmr Division is slow (it may take 20-100x the time of other arithmetic ops depending on CPU), so it seems a bad idea to use it. Why not just use checked_mul() and then checked_add() which are generally far faster, and also make the intent totally clear? |
@thestinger ? I imagine it's because rust simply didn't have checked_* On Mon, Nov 11, 2013 at 8:39 AM, bill-myers notifications@gh.neting.ccwrote:
|
@bill-myers the division is by a compile-time constant, so it will almost certainly be optimised to some combination of a shift and a multiplication (but only when optimisations are on). |
@huonw It's still going to be less efficient, since optimizing a division by non-power-of-two constant to a multiplication is not that easy (that is, you need a multiplication by multiplicative inverse and a loop, or an extending multiplication, shifts and other tricks); with checked_mul() you just check the carry flag or that the high part of extended multiplication is 0 |
@bill-myers that is true (i.e. it becomes a short series of multiplications + shifts... in fact, just checking now, LLVM optimises |
Suppress the triggering of some lints in derived structures Fixes rust-lang#10185 Fixes rust-lang#10417 For `integer_arithmetic`, `arithmetic_side_effects` and `shadow_reuse`. * ~~Not sure how to test these use-cases so feel free to point any method or any related PR.~~ --- changelog: FP: [`integer_arithmetic`], [`arithmetic_side_effects`]: No longer lint inside proc macros [rust-lang#10203](rust-lang/rust-clippy#10203) <!-- changelog_checked -->
Fixes #10271