libdap  Updated for version 3.20.6
libdap4 is an implementation of OPeNDAP's DAP protocol.
GNURegex.cc
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2005 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 
27 //#define DODS_DEBUG
28 
29 #include <config.h>
30 
31 #ifndef WIN32
32 #include <alloca.h>
33 #endif
34 #include <stdlib.h>
35 
36 #include <sys/types.h>
37 #include <regex.h>
38 
39 #include <new>
40 #include <string>
41 #include <vector>
42 #include <stdexcept>
43 
44 #include "GNURegex.h"
45 #include "Error.h"
46 #include "util.h"
47 #include "debug.h"
48 
49 
50 using namespace std;
51 
52 namespace libdap {
53 
54 void
55 Regex::init(const char *t)
56 {
57  DBG( cerr << "Regex::init() - BEGIN" << endl);
58 
59  DBG( cerr << "Regex::init() - creating new regex..." << endl);
60  d_preg = static_cast<void*>(new regex_t);
61 
62  DBG( cerr << "Regex::init() - Calling regcomp()..." << endl);
63  int result = regcomp(static_cast<regex_t*>(d_preg), t, REG_EXTENDED);
64 
65  if (result != 0) {
66  DBG( cerr << "Regex::init() - Call to regcomp FAILED" << endl);
67  DBG( cerr << "Regex::init() - Calling regerror()..." << endl);
68  size_t msg_len = regerror(result, static_cast<regex_t*>(d_preg),
69  static_cast<char*>(NULL),
70  static_cast<size_t>(0));
71 
72  DBG( cerr << "Regex::init() - Creating message" << endl);
73  vector<char> msg(msg_len+1);
74  //char *msg = new char[msg_len+1];
75  DBG( cerr << "Regex::init() - Calling regerror() again..." << endl);
76  regerror(result, static_cast<regex_t*>(d_preg), &msg[0], msg_len);
77  DBG( cerr << "Regex::init() - Throwing libdap::Error" << endl);
78  throw Error(string("Regex error: ") + string(&msg[0]));
79  //delete[] msg;
80  //throw e;
81  }
82  DBG( cerr << "Regex::init() - Call to regcomp() SUCCEEDED" << endl);
83  DBG( cerr << "Regex::init() - END" << endl);
84 }
85 
86 Regex::~Regex()
87 {
88  regfree(static_cast<regex_t*>(d_preg));
89  delete static_cast<regex_t*>(d_preg); d_preg = 0;
90 
91 }
92 
96 Regex::Regex(const char* t)
97 {
98  init(t);
99 }
100 
103 Regex::Regex(const char* t, int)
104 {
105  init(t);
106 }
107 
114 int
115 Regex::match(const char* s, int len, int pos)
116 {
117  if (len > 32766) // Integer overflow protection
118  return -1;
119 
120  regmatch_t *pmatch = new regmatch_t[len+1];
121  string ss = s;
122 
123  int result = regexec(static_cast<regex_t*>(d_preg),
124  ss.substr(pos, len-pos).c_str(), len, pmatch, 0);
125  int matchnum;
126  if (result == REG_NOMATCH)
127  matchnum = -1;
128  else
129  matchnum = pmatch[0].rm_eo - pmatch[0].rm_so;
130 
131  delete[] pmatch; pmatch = 0;
132 
133  return matchnum;
134 }
135 
146 int
147 Regex::search(const char* s, int len, int& matchlen, int pos)
148 {
149  // sanitize allocation
150  if (!size_ok(sizeof(regmatch_t), len+1))
151  return -1;
152 
153  // alloc space for len matches, which is theoretical max.
154  // Problem: If somehow 'len' is very large - say the size of a 32-bit int,
155  // then len+1 is a an integer overflow and this might be exploited by
156  // an attacker. It's not likely there will be more than a handful of
157  // matches, so I am going to limit this value to 32766. jhrg 3/4/09
158  if (len > 32766)
159  return -1;
160 
161  regmatch_t *pmatch = new regmatch_t[len+1];
162  string ss = s;
163 
164  int result = regexec(static_cast<regex_t*>(d_preg),
165  ss.substr(pos, len-pos).c_str(), len, pmatch, 0);
166  if (result == REG_NOMATCH) {
167  delete[] pmatch; pmatch = 0;
168  return -1;
169  }
170 
171  // Match found, find the first one (pmatch lists the longest first)
172  int m = 0;
173  for (int i = 1; i < len; ++i)
174  if (pmatch[i].rm_so != -1 && pmatch[i].rm_so < pmatch[m].rm_so)
175  m = i;
176 
177  matchlen = pmatch[m].rm_eo - pmatch[m].rm_so;
178  int matchpos = pmatch[m].rm_so;
179 
180  delete[] pmatch; pmatch = 0;
181  return matchpos;
182 }
183 
184 } // namespace libdap
185 
bool size_ok(unsigned int sz, unsigned int nelem)
sanitize the size of an array. Test for integer overflow when dynamically allocating an array...
Definition: util.cc:1148
STL namespace.
top level DAP object to house generic methods
Definition: AISConnect.cc:30