Skip to content

Commit a8ea099

Browse files
author
Tatiana Azundris Nuernberg
committed
Bug#20642505: HENRY SPENCER REGULAR EXPRESSIONS (REGEX) LIBRARY
The MySQL server uses Henry Spencer's library for regular expressions to support the REGEXP/RLIKE string operator. This changeset adapts a recent fix from the upstream for better 32-bit compatiblity. (Note that we cannot simply use the current upstream version as a drop-in replacement for the version used by the server as the latter has been extended to understand MySQL charsets etc.) (Adds unittest to 5.5 mergeset.)
2 parents 0ff896b + dc45e40 commit a8ea099

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

regex/regcomp.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
/* Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved.
2+
See file COPYRIGHT for details.
3+
4+
This file was modified by Oracle on 2015-05-18 for 32-bit compatibility.
5+
6+
Modifications copyright (c) 2015, Oracle and/or its affiliates. All rights
7+
reserved. */
8+
19
#include <my_global.h>
210
#include <m_string.h>
311
#include <m_ctype.h>
@@ -133,12 +141,26 @@ const CHARSET_INFO *charset;
133141
} else
134142
len = strlen((char *)pattern);
135143

144+
/*
145+
Find the maximum len we can safely process
146+
without a rollover and a mis-malloc.
147+
p->ssize is a sopno is a long (32+ bit signed);
148+
size_t is 16+ bit unsigned.
149+
*/
150+
{
151+
size_t new_ssize = len / (size_t)2 * (size_t)3 + (size_t)1; /* ugh */
152+
if ((new_ssize < len) || /* size_t rolled over */
153+
((SIZE_T_MAX / sizeof(sop)) < new_ssize) || /* malloc arg */
154+
(new_ssize > LONG_MAX)) /* won't fit in ssize */
155+
return(MY_REG_ESPACE); /* MY_REG_ESPACE or MY_REG_INVARG */
156+
p->ssize = new_ssize;
157+
}
158+
136159
/* do the mallocs early so failure handling is easy */
137160
g = (struct re_guts *)malloc(sizeof(struct re_guts) +
138161
(NC-1)*sizeof(cat_t));
139162
if (g == NULL)
140163
return(MY_REG_ESPACE);
141-
p->ssize = (long) (len/(size_t)2*(size_t)3 + (size_t)1); /* ugh */
142164
p->strip = (sop *)malloc(p->ssize * sizeof(sop));
143165
p->slen = 0;
144166
if (p->strip == NULL) {

unittest/gunit/my_regex-t.cc

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -80,4 +80,39 @@ TEST_F(RegexTest, BasicTest)
8080
}
8181
}
8282

83+
/*
84+
Bug#20642505: HENRY SPENCER REGULAR EXPRESSIONS (REGEX) LIBRARY
85+
86+
We have our own variant of the regex code that understands MySQL charsets.
87+
This test is hear to make sure that we never checkpoint or cherrypick from
88+
the upstream and end up with a version that isn't patched against a
89+
potential overflow.
90+
*/
91+
TEST_F(RegexTest, Bug20642505)
92+
{
93+
my_regex_t re;
94+
char *pattern;
95+
int err;
96+
size_t len= 684 * 1024 * 1024;
97+
98+
if ((sizeof(size_t) > 4) && (sizeof(long) > 4))
99+
return;
100+
101+
/* set up an empty C string as pattern as regcomp() will strlen() this */
102+
pattern= (char *) malloc(len);
103+
EXPECT_FALSE(pattern == NULL);
104+
memset(pattern, (int) ' ', len);
105+
pattern[len - 1]= '\0';
106+
107+
err= my_regcomp(&re, pattern, MY_REG_BASIC,
108+
&my_charset_latin1);
109+
110+
my_regfree(&re);
111+
free(pattern);
112+
113+
EXPECT_EQ(err, MY_REG_ESPACE)
114+
<< "my_regcomp returned " << err
115+
<< " instead of MY_REG_ESPACE (" << MY_REG_ESPACE << ")";
116+
}
117+
83118
} // namespace

0 commit comments

Comments
 (0)