diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 71736b1a49..1f2bacc5d5 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -280,6 +280,12 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) // Check for overlong array length. We cap it at the // maximum data size as we won't store more elements. + // e.g. this helps prevent user-controlled length fields + // from causing an excessive memory-allocation (for + // the array we'll be parsing into) unless they actually + // sent enough data to go along with it. Note that this check + // is *not* looking for whether the contents of the array will + // extend past the end of the data buffer. out_cc->println("if ( t_begin_of_data + %s > t_end_of_data + 1 || t_begin_of_data + %s < t_begin_of_data )", env->LValue(arraylength_var()), env->LValue(arraylength_var())); out_cc->inc_indent(); @@ -298,6 +304,28 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) env->LValue(arraylength_var())); out_cc->println("}"); out_cc->dec_indent(); + + if ( elemtype_->StaticSize(env) != -1 ) + { + // Boundary check the entire array if elements have static size. + string array_size = strfmt("((%d) * (%s))", + elemtype_->StaticSize(env), + env->RValue(arraylength_var())); + out_cc->println("// Check bounds for static-size array: %s", + data_id_str_.c_str()); + out_cc->println("if ( t_begin_of_data + %s > t_end_of_data || " + "t_begin_of_data + %s < t_begin_of_data )", + array_size.c_str(), array_size.c_str()); + out_cc->inc_indent(); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", + data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", + array_size.c_str(), + env->RValue(end_of_data), + env->RValue(begin_of_data)); + out_cc->dec_indent(); + elemtype_->SetBoundaryChecked(); + } } else if ( attr_restofdata_ ) {