1 /* Copyright (c) 2010, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22 
23 // First include (the generated) my_config.h, to get correct platform defines.
24 #include "my_config.h"
25 #include <gtest/gtest.h>
26 
27 #include "my_regex.h"
28 
29 /*
30   Thist is just a *very* basic test that things compile/link and execute.
31   The test data is taken from the first few lines in regex/tests.
32   For a full test suite, see regex/main.c which parses test input
33   and tests expected sucess/failure with basic/extended regexps etc. etc.
34  */
35 
36 namespace my_regex_unittest {
37 
38 const int NSUBS= 10;
39 
40 class RegexTest : public ::testing::Test
41 {
42 protected:
RegexTest()43   RegexTest()
44   {
45     memset(&re, 0, sizeof(re));
46   }
TearDownTestCase()47   static void TearDownTestCase()
48   {
49     my_regex_end();
50   }
51 
52   my_regmatch_t subs[NSUBS];
53   my_regex_t re;
54 };
55 
56 struct Re_test_data
57 {
58   const char* pattern;                          // Column 1 in regex/tests.
59   const int   cflags;                           // Column 2 in regex/tests.
60   const char* input;                            // Column 3 in regex/tests.
61 };
62 
63 Re_test_data basic_data[]=
64 {
65   { "a",      MY_REG_BASIC,    "a"   },
66   { "abc",    MY_REG_BASIC,    "abc" },
67   { "abc|de", MY_REG_EXTENDED, "abc" },
68   { "a|b|c",  MY_REG_EXTENDED, "abc" },
69   { NULL, 0, NULL }
70 };
71 
TEST_F(RegexTest,BasicTest)72 TEST_F(RegexTest, BasicTest)
73 {
74   for (int ix=0; basic_data[ix].pattern; ++ix)
75   {
76     EXPECT_EQ(0, my_regcomp(&re,
77                             basic_data[ix].pattern,
78                             basic_data[ix].cflags,
79                             &my_charset_latin1));
80 
81     int err= my_regexec(&re, basic_data[ix].input, NSUBS, subs, 0);
82     EXPECT_EQ(0, err)
83       << "my_regexec returned " << err
84       << " for pattern '" << basic_data[ix].pattern << "'"
85       << " with input '" << basic_data[ix].input << "'";
86     my_regfree(&re);
87   }
88 }
89 
90 /*
91   Bug#20642505: HENRY SPENCER REGULAR EXPRESSIONS (REGEX) LIBRARY
92 
93   We have our own variant of the regex code that understands MySQL charsets.
94   This test is hear to make sure that we never checkpoint or cherrypick from
95   the upstream and end up with a version that isn't patched against a
96   potential overflow.
97 */
TEST_F(RegexTest,Bug20642505)98 TEST_F(RegexTest, Bug20642505)
99 {
100   my_regex_t  re;
101   char       *pattern;
102   int         err;
103   size_t      len= 684 * 1024 * 1024;
104 
105   /*
106     We're testing on 32-bit/32-bit only. We could test e.g. with
107     64-bit size_t, 32-bit long (for 64-bit Windows and such), but
108     then we'd have to allocate twice as much memory, and it's a
109     bit heavy as it is.  (In 32/32, we exceed the size_t parameter
110     to malloc() as new_ssize exceeds UINT32 / 4, whereas in 64/32,
111     new_ssize would exceed LONG_MAX at UINT32 / 2.  (64/32 verified
112     in debugger.)
113   */
114   if ((sizeof(size_t) > 4) || (sizeof(long) > 4))
115     return;
116 
117   /* set up an empty C string as pattern as regcomp() will strlen() this */
118   pattern= (char *) malloc(len);
119   EXPECT_FALSE(pattern == NULL);
120   memset(pattern, (int) ' ', len);
121   pattern[len - 1]= '\0';
122 
123   err= my_regcomp(&re, pattern, MY_REG_BASIC,
124                   &my_charset_latin1);
125 
126   my_regfree(&re);
127   free(pattern);
128 
129   EXPECT_EQ(err, MY_REG_ESPACE)
130     << "my_regcomp returned " << err
131     << " instead of MY_REG_ESPACE (" << MY_REG_ESPACE << ")";
132 }
133 
134 }  // namespace
135