safec  2.1
Safe C Library - ISO TR24731 Bounds Checking Interface
strtok_s.c
Go to the documentation of this file.
1 /*------------------------------------------------------------------
2  * strtok_s.c
3  *
4  * October 2008, Bo Berry
5  *
6  * Copyright (c) 2008-2011 by Cisco Systems, Inc
7  * All rights reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person
10  * obtaining a copy of this software and associated documentation
11  * files (the "Software"), to deal in the Software without
12  * restriction, including without limitation the rights to use,
13  * copy, modify, merge, publish, distribute, sublicense, and/or
14  * sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following
16  * conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  *------------------------------------------------------------------
30  */
31 
32 #include "safeclib_private.h"
33 #include "safe_str_constraint.h"
34 #include "safe_str_lib.h"
35 
36 
154 char *
155 strtok_s(char * restrict dest, rsize_t * restrict dmax, const char * restrict src, char ** restrict ptr)
156 {
157 
158 #ifndef STRTOK_DELIM_MAX_LEN
159 #define STRTOK_DELIM_MAX_LEN 16
160 #endif
161 
162  const char *pt;
163  char *ptoken;
164  rsize_t dlen;
165  rsize_t slen;
166 
167  if (dmax == NULL) {
168  invoke_safe_str_constraint_handler("strtok_s: dmax is NULL",
169  NULL, ESNULLP);
170  return (NULL);
171  }
172 
173  if (*dmax == 0) {
174  invoke_safe_str_constraint_handler("strtok_s: dmax is 0",
175  NULL, ESZEROL);
176  return (NULL);
177  }
178 
179  if (*dmax > RSIZE_MAX_STR) {
180  invoke_safe_str_constraint_handler("strtok_s: dmax exceeds max",
181  NULL, ESLEMAX);
182  return (NULL);
183  }
184 
185  if (src == NULL) {
186  invoke_safe_str_constraint_handler("strtok_s: src is null",
187  NULL, ESNULLP);
188  return (NULL);
189  }
190 
191  if (ptr == NULL) {
192  invoke_safe_str_constraint_handler("strtok_s: ptr is null",
193  NULL, ESNULLP);
194  return (NULL);
195  }
196 
197  /* if the source was NULL, use the tokenizer context */
198  if (dest == NULL) {
199  dest = *ptr;
200  }
201 
202  /*
203  * scan dest for a delimiter
204  */
205  dlen = *dmax;
206  ptoken = NULL;
207  while (*dest != '\0' && !ptoken) {
208 
209  if (dlen == 0) {
210  *ptr = NULL;
212  "strtok_s: dest is unterminated",
213  NULL, ESUNTERM);
214  return (NULL);
215  }
216 
217  /*
218  * must scan the entire delimiter list
219  * ISO should have included a delimiter string limit!!
220  */
221  slen = STRTOK_DELIM_MAX_LEN;
222  pt = src;
223  while (*pt != '\0') {
224 
225  if (slen == 0) {
226  *ptr = NULL;
228  "strtok_s: src is unterminated",
229  NULL, ESUNTERM);
230  return (NULL);
231  }
232  slen--;
233 
234  if (*dest == *pt) {
235  ptoken = NULL;
236  break;
237  } else {
238  pt++;
239  ptoken = dest;
240  }
241  }
242  dest++;
243  dlen--;
244  }
245 
246  /*
247  * if the beginning of a token was not found, then no
248  * need to continue the scan.
249  */
250  if (ptoken == NULL) {
251  *dmax = dlen;
252  return (ptoken);
253  }
254 
255  /*
256  * Now we need to locate the end of the token
257  */
258  while (*dest != '\0') {
259 
260  if (dlen == 0) {
261  *ptr = NULL;
263  "strtok_s: dest is unterminated",
264  NULL, ESUNTERM);
265  return (NULL);
266  }
267 
268  slen = STRTOK_DELIM_MAX_LEN;
269  pt = src;
270  while (*pt != '\0') {
271 
272  if (slen == 0) {
273  *ptr = NULL;
275  "strtok_s: src is unterminated",
276  NULL, ESUNTERM);
277  return (NULL);
278  }
279  slen--;
280 
281  if (*dest == *pt) {
282  /*
283  * found a delimiter, set to null
284  * and return context ptr to next char
285  */
286  *dest = '\0';
287  *ptr = (dest + 1); /* return pointer for next scan */
288  *dmax = dlen - 1; /* account for the nulled delimiter */
289  return (ptoken);
290  } else {
291  /*
292  * simply scanning through the delimiter string
293  */
294  pt++;
295  }
296  }
297  dest++;
298  dlen--;
299  }
300 
301  *dmax = dlen;
302  return (ptoken);
303 }
#define STRTOK_DELIM_MAX_LEN
char * strtok_s(char *restrict dest, rsize_t *restrict dmax, const char *restrict src, char **restrict ptr)
A sequence of calls to the strtok_s function breaks the string pointed to by dest into a sequence of ...
Definition: strtok_s.c:155
void invoke_safe_str_constraint_handler(const char *msg, void *ptr, errno_t error)
Invokes the currently set constraint handler or the default.