CVE-2019-13225: NULL Pointer Dereference (CWE-476)
value: A NULL Pointer Dereference in match_at() in regexec.c in Oniguruma 6.9.2 allows attackers to potentially cause denial of service by providing a crafted regular expression. Oniguruma issues often affect Ruby, as well as common optional libraries for PHP and Rust.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 6.5
Published: 2019-07-10T14:15Z
Repository: https://github.com/kkos/oniguruma
Language: C
Files changed: src/regcomp.c
Commit date: 2019-07-06 17:16:46 +0900
Commit message: Fix CVE-2019-13225: problem in converting if-then-else pattern to bytecode.

Diff: diff --git a/src/regcomp.c b/src/regcomp.c
index c2c04a4..ff3431f 100644
--- a/src/regcomp.c
+++ b/src/regcomp.c
@@ -1305,12 +1305,13 @@ compile_length_bag_node(BagNode* node, regex_t* reg)
         tlen = compile_length_tree(Then, reg);
         if (tlen < 0) return tlen;
         len += tlen;
       }
 
+      len += SIZE_OP_JUMP + SIZE_OP_ATOMIC_END;
+
       if (IS_NOT_NULL(Else)) {
-        len += SIZE_OP_JUMP;
         tlen = compile_length_tree(Else, reg);
         if (tlen < 0) return tlen;
         len += tlen;
       }
     }
@@ -1453,11 +1454,11 @@ compile_bag_node(BagNode* node, regex_t* reg, ScanEnv* env)
     }
     break;
 
   case BAG_IF_ELSE:
     {
-      int cond_len, then_len, jump_len;
+      int cond_len, then_len, else_len, jump_len;
       Node* cond = NODE_BAG_BODY(node);
       Node* Then = node->te.Then;
       Node* Else = node->te.Else;
 
       r = add_op(reg, OP_ATOMIC_START);
@@ -1470,12 +1471,11 @@ compile_bag_node(BagNode* node, regex_t* reg, ScanEnv* env)
         if (then_len < 0) return then_len;
       }
       else
         then_len = 0;
 
-      jump_len = cond_len + then_len + SIZE_OP_ATOMIC_END;
-      if (IS_NOT_NULL(Else)) jump_len += SIZE_OP_JUMP;
+      jump_len = cond_len + then_len + SIZE_OP_ATOMIC_END + SIZE_OP_JUMP;
 
       r = add_op(reg, OP_PUSH);
       if (r != 0) return r;
       COP(reg)->push.addr = SIZE_INC_OP + jump_len;
 
@@ -1488,15 +1488,24 @@ compile_bag_node(BagNode* node, regex_t* reg, ScanEnv* env)
         r = compile_tree(Then, reg, env);
         if (r != 0) return r;
       }
 
       if (IS_NOT_NULL(Else)) {
-        int else_len = compile_length_tree(Else, reg);
-        r = add_op(reg, OP_JUMP);
-        if (r != 0) return r;
-        COP(reg)->jump.addr = else_len + SIZE_INC_OP;
+        else_len = compile_length_tree(Else, reg);
+        if (else_len < 0) return else_len;
+      }
+      else
+        else_len = 0;
 
+      r = add_op(reg, OP_JUMP);
+      if (r != 0) return r;
+      COP(reg)->jump.addr = SIZE_OP_ATOMIC_END + else_len + SIZE_INC_OP;
+
+      r = add_op(reg, OP_ATOMIC_END);
+      if (r != 0) return r;
+
+      if (IS_NOT_NULL(Else)) {
         r = compile_tree(Else, reg, env);
       }
     }
     break;
   }

Vulnerable code:         len += SIZE_OP_JUMP;
      int cond_len, then_len, jump_len;
      jump_len = cond_len + then_len + SIZE_OP_ATOMIC_END;
      if (IS_NOT_NULL(Else)) jump_len += SIZE_OP_JUMP;
        int else_len = compile_length_tree(Else, reg);
        r = add_op(reg, OP_JUMP);
        if (r != 0) return r;
        COP(reg)->jump.addr = else_len + SIZE_INC_OP;
Fixed code:       len += SIZE_OP_JUMP + SIZE_OP_ATOMIC_END;

      int cond_len, then_len, else_len, jump_len;
      jump_len = cond_len + then_len + SIZE_OP_ATOMIC_END + SIZE_OP_JUMP;
        else_len = compile_length_tree(Else, reg);
        if (else_len < 0) return else_len;
      }
      else
        else_len = 0;
      r = add_op(reg, OP_JUMP);
      if (r != 0) return r;
      COP(reg)->jump.addr = SIZE_OP_ATOMIC_END + else_len + SIZE_INC_OP;

      r = add_op(reg, OP_ATOMIC_END);
      if (r != 0) return r;

      if (IS_NOT_NULL(Else)) {