[CFF] oss-fuzz issue 11690 ASSERT: substr.offset >= opStart (#1461)
authorMichiharu Ariza <ariza@adobe.com>
Tue, 11 Dec 2018 20:21:24 +0000 (12:21 -0800)
committerBehdad Esfahbod <behdad@behdad.org>
Tue, 11 Dec 2018 20:21:24 +0000 (15:21 -0500)
* fix oss-fuzz 11690: substr.offset >= opStart

detect recursive subroutine call & handle as error

* fix build failure

* add minimized test case for oss-fuzz 11690

* removed asserts

src/hb-cff-interp-common.hh
src/hb-subset-cff-common.hh
src/hb-subset-cff1.cc
src/hb-subset-cff2.cc
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816 [new file with mode: 0644]

index effc081..6b81401 100644 (file)
@@ -332,8 +332,10 @@ struct ByteStr
   inline bool sanitize (hb_sanitize_context_t *c) const { return str->sanitize (c, len); }
 
   inline const HBUINT8& operator [] (unsigned int i) const {
-    assert (str && (i < len));
-    return (*str)[i];
+    if (likely (str && (i < len)))
+      return (*str)[i];
+    else
+      return Null(HBUINT8);
   }
 
   inline bool serialize (hb_serialize_context_t *c, const ByteStr &src)
@@ -628,7 +630,6 @@ struct ParsedValues
   {
     VAL *val = values.push ();
     val->op = op;
-    assert (substr.offset >= opStart);
     val->str = ByteStr (substr.str, opStart, substr.offset - opStart);
     opStart = substr.offset;
   }
@@ -637,7 +638,6 @@ struct ParsedValues
   {
     VAL *val = values.push (v);
     val->op = op;
-    assert (substr.offset >= opStart);
     val->str = ByteStr (substr.str, opStart, substr.offset - opStart);
     opStart = substr.offset;
   }
@@ -707,7 +707,6 @@ struct InterpEnv
 
   inline void pop_n_args (unsigned int n)
   {
-    assert (n <= argStack.get_count ());
     argStack.pop (n);
   }
 
index cd29d4e..7f3a12f 100644 (file)
@@ -526,11 +526,19 @@ struct SubrSubsetParam
   }
 
   template <typename ENV>
-  inline void set_current_str (ENV &env)
+  inline void set_current_str (ENV &env, bool calling)
   {
     ParsedCStr  *parsed_str = get_parsed_str_for_context (env.context);
     if (likely (parsed_str != nullptr))
-      current_parsed_str = parsed_str;
+    {
+      /* If the called subroutine is parsed partially but not completely yet,
+       * it must be because we are calling it recursively.
+       * Handle it as an error. */
+      if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.len > 0)))
+       env.set_error ();
+      else
+       current_parsed_str = parsed_str;
+    }
     else
       env.set_error ();
   }
index 7c8b14c..0a29226 100644 (file)
@@ -362,7 +362,7 @@ struct CFF1CSOpSet_SubrSubset : CFF1CSOpSet<CFF1CSOpSet_SubrSubset, SubrSubsetPa
        param.current_parsed_str->add_op (op, env.substr);
        param.current_parsed_str->set_parsed ();
        env.returnFromSubr ();
-       param.set_current_str (env);
+       param.set_current_str (env, false);
        break;
 
       case OpCode_endchar:
@@ -395,7 +395,7 @@ struct CFF1CSOpSet_SubrSubset : CFF1CSOpSet<CFF1CSOpSet_SubrSubset, SubrSubsetPa
     env.callSubr (subrs, type);
     param.current_parsed_str->add_call_op (op, substr, env.context.subr_num);
     hb_set_add (closure, env.context.subr_num);
-    param.set_current_str (env);
+    param.set_current_str (env, true);
   }
 
   private:
index f7df404..84608c1 100644 (file)
@@ -184,7 +184,7 @@ struct CFF2CSOpSet_SubrSubset : CFF2CSOpSet<CFF2CSOpSet_SubrSubset, SubrSubsetPa
       case OpCode_return:
        param.current_parsed_str->set_parsed ();
        env.returnFromSubr ();
-       param.set_current_str (env);
+       param.set_current_str (env, false);
        break;
 
       case OpCode_endchar:
@@ -216,7 +216,7 @@ struct CFF2CSOpSet_SubrSubset : CFF2CSOpSet<CFF2CSOpSet_SubrSubset, SubrSubsetPa
     env.callSubr (subrs, type);
     param.current_parsed_str->add_call_op (op, substr, env.context.subr_num);
     hb_set_add (closure, env.context.subr_num);
-    param.set_current_str (env);
+    param.set_current_str (env, true);
   }
 
   private:
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816
new file mode 100644 (file)
index 0000000..7f41718
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816 differ