]> Kevux Git Server - fll/commitdiff
Security: Invalid reads on NULL terminated strings with a max width greater than 1.
authorKevin Day <thekevinday@gmail.com>
Sun, 17 Jul 2022 23:42:21 +0000 (18:42 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 17 Jul 2022 23:42:21 +0000 (18:42 -0500)
The max width cannot be reliably trusted in NULL terminated strings.
Check if each character in the expected max width is not terminated early due to a NULL.
If it is, then adjust the max width.

level_0/f_print/c/private-print.c
level_0/f_print/c/private-print.h

index 16c34c3cb4f67318a0af3b9ee144d5b1ca07f14f..f6670225937fc71da7f06f3c723200d6c12844e2 100644 (file)
@@ -369,8 +369,7 @@ extern "C" {
       }
 
       if (string[i]) {
-        width = macro_f_utf_byte_width(string[i]);
-
+        width = private_f_print_width_max(string, i);
         safe = private_f_print_safely_get(string + i, width);
       }
       else {
@@ -502,8 +501,7 @@ extern "C" {
       }
 
       if (string[i]) {
-        width = macro_f_utf_byte_width(string[i]);
-
+        width = private_f_print_width_max(string, i);
         safe = private_f_print_safely_get(string + i, width);
       }
       else {
@@ -693,8 +691,7 @@ extern "C" {
       }
 
       if (string[i]) {
-        width = macro_f_utf_byte_width(string[i]);
-
+        width = private_f_print_width_max(string, i);
         safe = private_f_print_safely_get(string + i, width);
       }
       else {
@@ -800,8 +797,7 @@ extern "C" {
       }
 
       if (string[i]) {
-        width = macro_f_utf_byte_width(string[i]);
-
+        width = private_f_print_width_max(string, i);
         safe = private_f_print_safely_get(string + i, width);
       }
       else {
@@ -943,8 +939,7 @@ extern "C" {
     while (i < length) {
 
       if (string[i]) {
-        width = macro_f_utf_byte_width(string[i]);
-
+        width = private_f_print_width_max(string, i);
         safe = private_f_print_safely_get(string + i, width);
       }
       else {
@@ -1027,8 +1022,7 @@ extern "C" {
     while (i < length) {
 
       if (string[i]) {
-        width = macro_f_utf_byte_width(string[i]);
-
+        width = private_f_print_width_max(string, i);
         safe = private_f_print_safely_get(string + i, width);
       }
       else {
@@ -1148,6 +1142,35 @@ extern "C" {
   }
 #endif // !defined(_di_f_print_terminated_) || !defined(_di_f_print_raw_terminated_)
 
+#if !defined(_di_f_print_except_dynamic_partial_raw_) || !defined(_di_f_print_except_dynamic_partial_safely_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_in_dynamic_partial_raw_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) || !defined(_di_f_print_except_in_dynamic_raw_safely_) || !defined(_di_f_print_except_in_dynamic_safely_) || !defined(_di_f_print_except_in_raw_safely_) || !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_raw_safely_) || !defined(_di_f_print_except_safely_) || !defined(_di_f_print_raw_safely_) || !defined(_di_f_print_raw_safely_dynamic_) || !defined(_di_f_print_raw_safely_dynamic_partial_) || !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_)
+  uint8_t private_f_print_width_max(const f_string_t string, const f_array_length_t at) {
+
+    const uint8_t width = macro_f_utf_byte_width(string[at]);
+
+    if (width > 1) {
+      if (string[at + 1]) {
+        if (width > 2) {
+          if (string[at + 2]) {
+            if (width > 3) {
+              if (!string[at + 3]) {
+                return 3;
+              }
+            }
+          }
+          else {
+            return 2;
+          }
+        }
+      }
+      else {
+        return 1;
+      }
+    }
+
+    return width;
+  }
+#endif // !defined(_di_f_print_except_dynamic_partial_raw_) || !defined(_di_f_print_except_dynamic_partial_safely_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_in_dynamic_partial_raw_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) || !defined(_di_f_print_except_in_dynamic_raw_safely_) || !defined(_di_f_print_except_in_dynamic_safely_) || !defined(_di_f_print_except_in_raw_safely_) || !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_raw_safely_) || !defined(_di_f_print_except_safely_) || !defined(_di_f_print_raw_safely_) || !defined(_di_f_print_raw_safely_dynamic_) || !defined(_di_f_print_raw_safely_dynamic_partial_) || !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_)
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index d580e8ecc4f5dd24c87e477c0d96caed253c2e76..fc94f5e840c4caa457b92af4c4690b3d60ef3319 100644 (file)
@@ -562,6 +562,40 @@ extern "C" {
   extern f_status_t private_f_print_terminated(const f_string_t string, FILE * const stream) F_attribute_visibility_internal_d;
 #endif // !defined(_di_f_print_terminated_) || !defined(_di_f_print_raw_terminated_)
 
+/**
+ * Determine max width, which is the shorter of the byte width and the remaining characters in the string.
+ *
+ * @param string
+ *   The string to process.
+ * @param at
+ *   The position in the string representing a single character to get the width of.
+ *
+ * @return
+ *   The determined with (the max size is 4).
+ *
+ * @see f_print_except_dynamic_partial_raw()
+ * @see f_print_except_dynamic_partial_safely()
+ * @see f_print_except_dynamic_raw()
+ * @see f_print_except_dynamic_safely()
+ * @see f_print_except_in_dynamic_partial_raw_safely()
+ * @see f_print_except_in_dynamic_partial_safely()
+ * @see f_print_except_in_dynamic_raw_safely()
+ * @see f_print_except_in_dynamic_safely()
+ * @see f_print_except_in_raw_safely()
+ * @see f_print_except_in_safely()
+ * @see f_print_except_raw_safely()
+ * @see f_print_except_safely()
+ * @see f_print_raw_safely()
+ * @see f_print_raw_safely_dynamic()
+ * @see f_print_raw_safely_dynamic_partial()
+ * @see f_print_safely()
+ * @see f_print_safely_dynamic()
+ * @see f_print_safely_dynamic_partial()
+ */
+#if !defined(_di_f_print_except_dynamic_partial_raw_) || !defined(_di_f_print_except_dynamic_partial_safely_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_in_dynamic_partial_raw_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) || !defined(_di_f_print_except_in_dynamic_raw_safely_) || !defined(_di_f_print_except_in_dynamic_safely_) || !defined(_di_f_print_except_in_raw_safely_) || !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_raw_safely_) || !defined(_di_f_print_except_safely_) || !defined(_di_f_print_raw_safely_) || !defined(_di_f_print_raw_safely_dynamic_) || !defined(_di_f_print_raw_safely_dynamic_partial_) || !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_)
+  extern uint8_t private_f_print_width_max(const f_string_t string, const f_array_length_t at) F_attribute_visibility_internal_d;
+#endif // !defined(_di_f_print_except_dynamic_partial_raw_) || !defined(_di_f_print_except_dynamic_partial_safely_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_in_dynamic_partial_raw_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) || !defined(_di_f_print_except_in_dynamic_raw_safely_) || !defined(_di_f_print_except_in_dynamic_safely_) || !defined(_di_f_print_except_in_raw_safely_) || !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_raw_safely_) || !defined(_di_f_print_except_safely_) || !defined(_di_f_print_raw_safely_) || !defined(_di_f_print_raw_safely_dynamic_) || !defined(_di_f_print_raw_safely_dynamic_partial_) || !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_)
+
 #ifdef __cplusplus
 } // extern "C"
 #endif