summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-06-25 16:14:06 -0400
committerZack Rusin <[email protected]>2013-06-28 04:24:16 -0400
commit2f13f28120fdfe2f5a64e87b4ec19db94bf63713 (patch)
treec30e81d22420c8dd1e594081a821eeb7a0e804be
parente742f7788ea6f2c1a4e1071a2d53eef5939e501b (diff)
draw: check for an integer overflow when computing stride
Our buffer overflow arithmetic was susceptible to integer overflows which was the buffer overflow logic to break. Lets use the llvm overflow intrinsics to check for integer overflows while computing the stride/needed buffer size. Signed-off-by: Zack Rusin <[email protected]>
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c53
1 files changed, 43 insertions, 10 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index f27776a5cc5..c1b4acd25a8 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -699,6 +699,13 @@ generate_fetch(struct gallivm_state *gallivm,
LLVMValueRef temp_ptr =
lp_build_alloca(gallivm,
lp_build_vec_type(gallivm, lp_float32_vec4_type()), "");
+ LLVMValueRef ofbit, oresult;
+ LLVMTypeRef oelems[2] = {
+ LLVMInt32TypeInContext(gallivm->context),
+ LLVMInt1TypeInContext(gallivm->context)
+ };
+ LLVMTypeRef otype = LLVMStructTypeInContext(gallivm->context,
+ oelems, 2, FALSE);
struct lp_build_if_state if_ctx;
if (velem->instance_divisor) {
@@ -708,23 +715,49 @@ generate_fetch(struct gallivm_state *gallivm,
"instance_divisor");
}
- stride = LLVMBuildMul(builder, vb_stride, index, "");
+ oresult = lp_build_intrinsic_binary(builder,
+ "llvm.umul.with.overflow.i32",
+ otype, vb_stride, index);
+ ofbit = LLVMBuildExtractValue(builder, oresult, 1, "");
+ stride = LLVMBuildExtractValue(builder, oresult, 0, "");
+
+ oresult = lp_build_intrinsic_binary(builder,
+ "llvm.uadd.with.overflow.i32",
+ otype, stride, vb_buffer_offset);
+ ofbit = LLVMBuildOr(
+ builder, ofbit,
+ LLVMBuildExtractValue(builder, oresult, 1, ""),
+ "");
+ stride = LLVMBuildExtractValue(builder, oresult, 0, "");
+
+ oresult = lp_build_intrinsic_binary(
+ builder,
+ "llvm.uadd.with.overflow.i32",
+ otype, stride,
+ lp_build_const_int32(gallivm, velem->src_offset));
+ ofbit = LLVMBuildOr(
+ builder, ofbit,
+ LLVMBuildExtractValue(builder, oresult, 1, ""),
+ "");
+ stride = LLVMBuildExtractValue(builder, oresult, 0, "");
- stride = LLVMBuildAdd(builder, stride,
- vb_buffer_offset,
- "");
- stride = LLVMBuildAdd(builder, stride,
- lp_build_const_int32(gallivm, velem->src_offset),
- "");
- needed_buffer_size = LLVMBuildAdd(
- builder, stride,
+
+ oresult = lp_build_intrinsic_binary(
+ builder,
+ "llvm.uadd.with.overflow.i32",
+ otype, stride,
lp_build_const_int32(gallivm,
- util_format_get_blocksize(velem->src_format)),
+ util_format_get_blocksize(velem->src_format)));
+ ofbit = LLVMBuildOr(
+ builder, ofbit,
+ LLVMBuildExtractValue(builder, oresult, 1, ""),
"");
+ needed_buffer_size = LLVMBuildExtractValue(builder, oresult, 0, "");
buffer_overflowed = LLVMBuildICmp(builder, LLVMIntUGT,
needed_buffer_size, buffer_size,
"buffer_overflowed");
+ buffer_overflowed = LLVMBuildOr(builder, buffer_overflowed, ofbit, "");
#if 0
lp_build_printf(gallivm, "vbuf index = %u, vb_stride is %u\n",
index, vb_stride);