From dea292bf590a7ef851a5c97a1be8ae6d7ba6ed4b Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 5 Sep 2021 16:55:46 -0500 Subject: [PATCH] Security: Static/Dynamic string compare functions aren't properly handling empty strings or empty ranges. When the static/dynamic string has used = 0 or the range.start > range.stop, then the string (or range) is empty. The private function isn't aware of this and simply attempts to access the invalid ranges. This will result in an invalid read. Add the missing used and range checks. --- level_1/fl_string/c/string.c | 132 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/level_1/fl_string/c/string.c b/level_1/fl_string/c/string.c index 8a2a89a..2598ee6 100644 --- a/level_1/fl_string/c/string.c +++ b/level_1/fl_string/c/string.c @@ -84,6 +84,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used || range1.start > range1.stop) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare(string1.string, string2.string, range1.start, range2.start, range1.stop + 1, range2.stop + 1); } #endif // _di_fl_string_dynamic_partial_compare_ @@ -94,6 +105,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare(string1.string, string2.string, 0, range2.start, string1.used, range2.stop + 1); } #endif // _di_fl_string_dynamic_partial_compare_dynamic_ @@ -104,6 +126,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!length1) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare(string1, string2.string, 0, range2.start, length1, range2.stop + 1); } #endif // _di_fl_string_dynamic_partial_compare_string_ @@ -115,6 +148,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used || range1.start > range1.stop) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_except(string1.string, string2.string, range1.start, range2.start, range1.stop + 1, range2.stop + 1, except1, except2); } #endif // _di_fl_string_dynamic_partial_compare_except_ @@ -125,6 +169,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_except(string1.string, string2.string, 0, range2.start, string1.used, range2.stop + 1, except1, except2); } #endif // _di_fl_string_dynamic_partial_compare_except_dynamic_ @@ -135,6 +190,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!length1) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_except(string1, string2.string, 0, range2.start, length1, range2.stop + 1, except1, except2); } #endif // _di_fl_string_dynamic_partial_compare_except_string_ @@ -146,6 +212,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used || range1.start > range1.stop) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_except_trim(string1.string, string2.string, range1.start, range2.start, range1.stop + 1, range2.stop + 1, except1, except2); } #endif // _di_fl_string_dynamic_partial_compare_except_trim_ @@ -156,6 +233,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_except_trim(string1.string, string2.string, 0, range2.start, string1.used, range2.stop + 1, except1, except2); } #endif // _di_fl_string_dynamic_partial_compare_except_trim_dynamic_ @@ -166,6 +254,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!length1) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_except_trim(string1, string2.string, 0, range2.start, length1, range2.stop + 1, except1, except2); } #endif // _di_fl_string_dynamic_partial_compare_except_trim_string_ @@ -177,6 +276,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used || range1.start > range1.stop) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_trim(string1.string, string2.string, range1.start, range2.start, range1.stop + 1, range2.stop + 1); } #endif // _di_fl_string_dynamic_partial_compare_trim_ @@ -187,6 +297,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!string1.used) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_trim(string1.string, string2.string, 0, range2.start, string1.used, range2.stop + 1); } #endif // _di_fl_string_dynamic_partial_compare_trim_dynamic_ @@ -197,6 +318,17 @@ extern "C" { if (string2.used <= range2.stop) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ + if (!length1) { + if (!string2.used || range2.start > range2.stop) { + return F_equal_to; + } + + return F_equal_to_not; + } + else if (!string2.used || range2.start > range2.stop) { + return F_equal_to_not; + } + return private_fl_string_compare_trim(string1, string2.string, 0, range2.start, length1, range2.stop + 1); } #endif // _di_fl_string_dynamic_partial_compare_trim_string_ -- 1.8.3.1