-
Notifications
You must be signed in to change notification settings - Fork 1.1k
runtime: fix pointer calculations to avoid overflows. Fixes #5713. #5716
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,7 +89,7 @@ WEAK device_copy make_buffer_copy(const halide_buffer_t *src, bool src_host, | |
// Offset the src base pointer to the right point in its buffer. | ||
c.src_begin = 0; | ||
for (int i = 0; i < src->dimensions; i++) { | ||
c.src_begin += src->dim[i].stride * (dst->dim[i].min - src->dim[i].min); | ||
c.src_begin += (uint64_t)src->dim[i].stride * (dst->dim[i].min - src->dim[i].min); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just noticed this on the last skim: should this be int64_t ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fields in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking that the RHS here could be signed (as opposed to the two examples below, where it seems harmless to cast to uint64). But I agree that there are other issues here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should indeed be int64_t. The operations required to compute an offset given some strides, etc are multiplications, subtractions, additions. None of those differ between signed and unsigned (yay modulo arithmetic), so none of that matters. But there are also upcasts, and those are the only thing that differs between sign and unsigned. The source field is an int32_t, so it must be sign-extended. This PR casts an int32_t to a uint64_t. I'm honestly not sure whether that sign or zero extends. Using an int64_t would make it clear that it's sign-extending it. The rest of the arithmetic is invariant to signed vs unsigned. There may be bugs elsewhere when the strides are negative, but let's not add a new one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is c.src_begin += (uint64_t)((int64_t)src->dim[i].stride * (dst->dim[i].min - src->dim[i].min)); The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we might want src_begin to decrease in value, and we may want to support negative strides in future. For now we should just write new code assuming they could be negative. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, but to be clear - There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some parts of Halide support negative strides and some don't. device buffer copies currently do not. So in this code, stride is currently not going to be negative (or other things would break too). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In theory, negative strides should be fully supported. As you've noticed, though, this is undertested (probably for both normal and |
||
} | ||
c.src_begin *= c.chunk_size; | ||
|
||
|
@@ -114,8 +114,8 @@ WEAK device_copy make_buffer_copy(const halide_buffer_t *src, bool src_host, | |
// in ascending order in the dst. | ||
for (int i = 0; i < dst->dimensions; i++) { | ||
// TODO: deal with negative strides. | ||
uint64_t dst_stride_bytes = dst->dim[i].stride * dst->type.bytes(); | ||
uint64_t src_stride_bytes = src->dim[i].stride * src->type.bytes(); | ||
uint64_t dst_stride_bytes = (uint64_t)dst->dim[i].stride * dst->type.bytes(); | ||
uint64_t src_stride_bytes = (uint64_t)src->dim[i].stride * src->type.bytes(); | ||
// Insert the dimension sorted into the buffer copy. | ||
int insert; | ||
for (insert = 0; insert < i; insert++) { | ||
|
@@ -172,7 +172,7 @@ WEAK device_copy make_device_to_host_copy(const halide_buffer_t *buf) { | |
ALWAYS_INLINE int64_t calc_device_crop_byte_offset(const struct halide_buffer_t *src, struct halide_buffer_t *dst) { | ||
int64_t offset = 0; | ||
for (int i = 0; i < src->dimensions; i++) { | ||
offset += (dst->dim[i].min - src->dim[i].min) * src->dim[i].stride; | ||
offset += (dst->dim[i].min - src->dim[i].min) * (int64_t)src->dim[i].stride; | ||
} | ||
offset *= src->type.bytes(); | ||
return offset; | ||
|
@@ -181,7 +181,7 @@ ALWAYS_INLINE int64_t calc_device_crop_byte_offset(const struct halide_buffer_t | |
// Caller is expected to verify that src->dimensions == dst->dimensions + 1, | ||
// and that slice_dim and slice_pos are valid within src | ||
ALWAYS_INLINE int64_t calc_device_slice_byte_offset(const struct halide_buffer_t *src, int slice_dim, int slice_pos) { | ||
int64_t offset = (slice_pos - src->dim[slice_dim].min) * src->dim[slice_dim].stride; | ||
int64_t offset = (slice_pos - src->dim[slice_dim].min) * (int64_t)src->dim[slice_dim].stride; | ||
offset *= src->type.bytes(); | ||
return offset; | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.