Browse Source

fix uninitialized memory in regex expression parsing and correct problems with allowed character lists

Kolja Strohm 1 week ago
parent
commit
513cba4c3d
3 changed files with 69 additions and 18 deletions
  1. 58 9
      Framework Tests/Regex.cpp
  2. 4 4
      Regex.cpp
  3. 7 5
      Regex.h

+ 58 - 9
Framework Tests/Regex.cpp

@@ -73,13 +73,13 @@ namespace FrameworkTests
         TEST_METHOD (MatchTest3)
         {
             auto parser = Framework::Regex::parse("(?:abc)*");
-            auto result = parser->match("_aabcabcc", (int)strlen(" aabcabcc")); 
+            auto result = parser->match("_aabcabcc", (int)strlen(" aabcabcc"));
             Assert::IsTrue(result->getEintragAnzahl() == 5,
                 L"Invalid result count while matching '_aabcabcc' against "
                 L"'(?:abc)*'");
-            auto* first = result->z(0); 
-            auto* second = result->z(1); 
-            auto* third = result->z(2); 
+            auto* first = result->z(0);
+            auto* second = result->z(1);
+            auto* third = result->z(2);
             auto* forth = result->z(3);
             auto* fifth = result->z(4);
             Assert::IsTrue(first->getStart() == 0 && first->getEnd() == 0,
@@ -127,8 +127,8 @@ namespace FrameworkTests
             auto result = parser->match("_aabcabcc", (int)strlen(" aabcabcc"));
             Assert::IsTrue(result->getEintragAnzahl() == 8,
                 L"Invalid result count while matching '_aabcabcc' against "
-                L"'(?:abc)*?'"); 
-            auto* _0 = result->z(0); 
+                L"'(?:abc)*?'");
+            auto* _0 = result->z(0);
             auto* _1 = result->z(1);
             auto* _2 = result->z(2);
             auto* _3 = result->z(3);
@@ -199,7 +199,8 @@ namespace FrameworkTests
         TEST_METHOD (MatchTest5)
         {
             auto parser = Framework::Regex::parse("(a|b)+");
-            auto result = parser->match("cabaccccbab", (int)strlen("cabaccccbab"));
+            auto result
+                = parser->match("cabaccccbab", (int)strlen("cabaccccbab"));
             Assert::IsTrue(result->getEintragAnzahl() == 2,
                 L"Invalid result count while matching 'cabaccccbab' against "
                 L"'a|b'");
@@ -236,8 +237,7 @@ namespace FrameworkTests
         TEST_METHOD (MatchTest6)
         {
             auto parser = Framework::Regex::parse("(?:^|c)ab");
-            auto result
-                = parser->match("abcabcasd", (int)strlen("abcabcasd"));
+            auto result = parser->match("abcabcasd", (int)strlen("abcabcasd"));
             Assert::IsTrue(result->getEintragAnzahl() == 2,
                 L"Invalid result count while matching 'abcabcasd' against "
                 L"'(?:^|c)ab'");
@@ -286,5 +286,54 @@ namespace FrameworkTests
             result->release();
             parser->release();
         }
+
+        TEST_METHOD (TestNumber0)
+        {
+            auto parser = Framework::Regex::parse("^[0-9]+$");
+            auto* results = parser->match("0", 1);
+            bool ok = results->getEintragAnzahl() == 1;
+            results->release();
+            parser->release();
+            Assert::IsTrue(
+                ok, L"no result found while matcging '0' against '^[0-9]+$'");
+        }
+
+        TEST_METHOD (TestNumber1)
+        {
+            auto parser = Framework::Regex::parse("^[0-9]+(\\.[0-9]+)?$");
+            auto* results = parser->match("0", 1);
+            bool ok = results->getEintragAnzahl() == 1;
+            results->release();
+            parser->release();
+            Assert::IsTrue(ok,
+                L"no result found while matcging '0' against "
+                L"'^[0-9]+(\\.[0-9]+)?$'");
+        }
+
+        TEST_METHOD (TestNumber2)
+        {
+            auto parser = Framework::Regex::parse(
+                "^[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$");
+            auto* results = parser->match("0", 1);
+            bool ok = results->getEintragAnzahl() == 1;
+            results->release();
+            parser->release();
+            Assert::IsTrue(ok,
+                L"no result found while matcging '0' against "
+                L"'^[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$'");
+        }
+
+        TEST_METHOD (TestNumber3)
+        {
+            auto parser = Framework::Regex::parse(
+                "^[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$");
+            auto* results = parser->match("1e-3", 1);
+            bool ok = results->getEintragAnzahl() == 1;
+            results->release();
+            parser->release();
+            Assert::IsTrue(ok,
+                L"no result found while matcging '1e-3' against "
+                L"'^[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$'");
+        }
     };
 } // namespace FrameworkTests

+ 4 - 4
Regex.cpp

@@ -57,13 +57,13 @@ Automata<char>* parseCharacterList(Text* regex, RegexConfig& config)
         case '-':
             if (escaped || !minusValid)
             {
-                characterList += '-';
+                characterList += "-";
             }
             else if (minusValid)
             {
                 if (i == length - 1)
                 {
-                    characterList += '-';
+                    characterList += "-";
                 }
                 else
                 {
@@ -80,12 +80,12 @@ Automata<char>* parseCharacterList(Text* regex, RegexConfig& config)
                     }
                     for (unsigned char c = before; c <= after; c++)
                     {
-                        characterList += c;
+                        characterList.append((char)c);
                     }
                     i++;
                 }
-                break;
             }
+            break;
         default:
             {
                 if (escaped)

+ 7 - 5
Regex.h

@@ -28,7 +28,8 @@ namespace Framework
         public:
             Transition()
                 : conditionFunction(0),
-                  zTarget(0)
+                  zTarget(0),
+                  requiredFlags(0)
             {}
 
             Transition(std::function<bool(Data, int)> conditionFunction,
@@ -41,7 +42,8 @@ namespace Framework
 
             Transition(const Transition& other)
                 : conditionFunction(other.conditionFunction),
-                  zTarget(other.zTarget)
+                  zTarget(other.zTarget),
+                  requiredFlags(other.requiredFlags)
             {}
 
             bool test(Data value, int flags) const
@@ -326,12 +328,12 @@ namespace Framework
                 while (currentFrame)
                 {
                     if (currentFrame->getStrIndex() >= length)
-					{
-						flags |= Flags::END;
+                    {
+                        flags |= Flags::END;
                     }
                     else
                     {
-						flags &= ~Flags::END;
+                        flags &= ~Flags::END;
                     }
                     if (currentFrame->getStrIndex() == 0)
                     {