CVE-2021-45931 (published 2022-01-01T01:15Z)

HarfBuzz 2.9.0 has an out-of-bounds write in hb_bit_set_invertible_t::set (called from hb_sparseset_t<hb_bit_set_invertible_t>::set and hb_set_copy).

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-787
cwe_name: Out-of-bounds Write
description: The product writes data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/harfbuzz/harfbuzz
commit_details: repo_url: https://github.com/harfbuzz/harfbuzz
author: Behdad Esfahbod
author_date: 2021-08-24 10:31:49-06:00
msg: [set] Make all operators null-safe again

Changed my mind.

Also for hb_map_clear().

Part of https://github.com/harfbuzz/harfbuzz/pull/3162
repository: repo_url: https://github.com/harfbuzz/harfbuzz
repo_name: harfbuzz/harfbuzz
description: HarfBuzz text shaping engine
repo_language: C++
owner: harfbuzz
file_changes: filename: hb-bit-set-invertible.hh
change_type: ModificationType.MODIFY
diff: @@ -46,9 +46,22 @@ struct hb_bit_set_invertible_t
   bool in_error () const { return s.in_error (); }
   explicit operator bool () const { return !is_empty (); }
 
-  void reset () { s.reset (); inverted = false; }
-  void clear () { s.clear (); inverted = false; }
-  void invert () { inverted = !inverted; }
+  void reset ()
+  {
+    s.reset ();
+    inverted = false;
+  }
+  void clear ()
+  {
+    s.clear ();
+    if (likely (s.successful))
+      inverted = false;
+  }
+  void invert ()
+  {
+    if (likely (s.successful))
+      inverted = !inverted;
+  }
 
   bool is_empty () const
   {
@@ -116,7 +129,12 @@ struct hb_bit_set_invertible_t
     return next (&c) && c <= last;
   }
 
-  void set (const hb_bit_set_invertible_t &other) { s.set (other.s); inverted = other.inverted; }
+  void set (const hb_bit_set_invertible_t &other)
+  {
+    s.set (other.s);
+    if (likely (s.successful))
+      inverted = other.inverted;
+  }
 
   bool is_equal (const hb_bit_set_invertible_t &other) const
   {
@@ -161,7 +179,8 @@ struct hb_bit_set_invertible_t
       else
 	process (hb_bitwise_lt, other);
     }
-    inverted = inverted || other.inverted;
+    if (likely (s.successful))
+      inverted = inverted || other.inverted;
   }
   void intersect (const hb_bit_set_invertible_t &other)
   {
@@ -179,7 +198,8 @@ struct hb_bit_set_invertible_t
       else
 	process (hb_bitwise_gt, other);
     }
-    inverted = inverted && other.inverted;
+    if (likely (s.successful))
+      inverted = inverted && other.inverted;
   }
   void subtract (const hb_bit_set_invertible_t &other)
   {
@@ -197,12 +217,14 @@ struct hb_bit_set_invertible_t
       else
 	process (hb_bitwise_and, other);
     }
-    inverted = inverted && !other.inverted;
+    if (likely (s.successful))
+      inverted = inverted && !other.inverted;
   }
   void symmetric_difference (const hb_bit_set_invertible_t &other)
   {
     process (hb_bitwise_xor, other);
-    inverted = inverted ^ other.inverted;
+    if (likely (s.successful))
+      inverted = inverted ^ other.inverted;
   }
 
   bool next (hb_codepoint_t *codepoint) const

programming_language: C++
filename: hb-map.cc
change_type: ModificationType.MODIFY
diff: @@ -255,9 +255,6 @@ hb_map_has (const hb_map_t *map,
 void
 hb_map_clear (hb_map_t *map)
 {
-  if (unlikely (hb_object_is_immutable (map)))
-    return;
-
   return map->clear ();
 }
 

programming_language: PHP
filename: hb-map.hh
change_type: ModificationType.MODIFY
diff: @@ -169,6 +169,8 @@ struct hb_hashmap_t
 
   void clear ()
   {
+    if (unlikely (!successful)) return;
+
     if (items)
       for (auto &_ : hb_iter (items, mask + 1))
 	_.clear ();

programming_language: C
filename: hb-set.cc
change_type: ModificationType.MODIFY
diff: @@ -201,9 +201,7 @@ hb_set_copy (const hb_set_t *set)
 void
 hb_set_clear (hb_set_t *set)
 {
-  if (unlikely (hb_object_is_immutable (set)))
-    return;
-
+  /* Immutible-safe. */
   set->clear ();
 }
 
@@ -368,9 +366,7 @@ void
 hb_set_set (hb_set_t       *set,
 	    const hb_set_t *other)
 {
-  if (unlikely (hb_object_is_immutable (set)))
-    return;
-
+  /* Immutible-safe. */
   set->set (*other);
 }
 
@@ -387,9 +383,7 @@ void
 hb_set_union (hb_set_t       *set,
 	      const hb_set_t *other)
 {
-  if (unlikely (hb_object_is_immutable (set)))
-    return;
-
+  /* Immutible-safe. */
   set->union_ (*other);
 }
 
@@ -406,9 +400,7 @@ void
 hb_set_intersect (hb_set_t       *set,
 		  const hb_set_t *other)
 {
-  if (unlikely (hb_object_is_immutable (set)))
-    return;
-
+  /* Immutible-safe. */
   set->intersect (*other);
 }
 
@@ -425,9 +417,7 @@ void
 hb_set_subtract (hb_set_t       *set,
 		 const hb_set_t *other)
 {
-  if (unlikely (hb_object_is_immutable (set)))
-    return;
-
+  /* Immutible-safe. */
   set->subtract (*other);
 }
 
@@ -445,9 +435,7 @@ void
 hb_set_symmetric_difference (hb_set_t       *set,
 			     const hb_set_t *other)
 {
-  if (unlikely (hb_object_is_immutable (set)))
-    return;
-
+  /* Immutible-safe. */
   set->symmetric_difference (*other);
 }
 
@@ -462,9 +450,7 @@ hb_set_symmetric_difference (hb_set_t       *set,
 void
 hb_set_invert (hb_set_t *set)
 {
-  if (unlikely (hb_object_is_immutable (set)))
-    return;
-
+  /* Immutible-safe. */
   set->invert ();
 }
 

programming_language: C