Merge lp:~jamesodhunt/libnih/fix-for-bug-834813 into lp:libnih

Proposed by James Hunt on 2011-08-31
Status: Merged
Merged at revision: 1053
Proposed branch: lp:~jamesodhunt/libnih/fix-for-bug-834813
Merge into: lp:libnih
Diff against target: 440 lines (+396/-1)
3 files modified
ChangeLog (+8/-0)
nih/string.c (+8/-1)
nih/tests/test_string.c (+380/-0)
To merge this branch: bzr merge lp:~jamesodhunt/libnih/fix-for-bug-834813
Reviewer Review Type Date Requested Status
Scott James Remnant 2011-08-31 Pending
Review via email: mp+73575@code.launchpad.net

This proposal supersedes a proposal from 2011-08-31.

Description of the change

Final attempt I hope.

  * ChangeLog: updated.
  * nih/string.c (nih_str_split): Fixes to avoid over-running
    input string and also returning an empty string array entry
    when repeat is true (LP: #834813).
  * nih/tests/test_string.c (test_str_split): Added a lot of new
    tests for nih_str_split().

To post a comment you must log in.
Scott James Remnant (scott) wrote : Posted in a previous version of this proposal

"str && *str" shouldn't be necessary, this function already asserts "str != NULL"

Have you checked other uses of strchr() in the code, I probably make the same mistake all over the place - believing it would return NULL if given '\0'

I'd like that final if() cleaned up, it doesn't make sense what you're doing there - perhaps splitting out some informationally named temporary variables and checking those would make more sense, or using some other method

review: Needs Fixing
James Hunt (jamesodhunt) wrote : Posted in a previous version of this proposal

> "str && *str" shouldn't be necessary, this function already asserts "str !=
> NULL"
>
> Have you checked other uses of strchr() in the code, I probably make the same
> mistake all over the place - believing it would return NULL if given '\0'
>
> I'd like that final if() cleaned up, it doesn't make sense what you're doing
> there - perhaps splitting out some informationally named temporary variables
> and checking those would make more sense, or using some other method
Hi Scott,

Firstly, I've raised a bug on strchr(3) and memchr(3) since they do not currently specify the behaviour should the char to search for be '\0':

https://bugzilla.kernel.org/show_bug.cgi?id=42042

I've reworked (simplified) the change to nih_str_split(). Note that the "continue" is safe since we consume any and all multiple delimiter characters on the next loop iteration.

The assert protects the function initially, but since we're incrementing 'str' we do need atleast the first "str && *str" check...

   while (repeat && str && *str && strchr (delim, *str))

...since without it, we overrun the string, and the new tests will fail. The subsequent "str && *str"'s may not be strictly required, but as this bug was rather subtle anyway, I'd be tempted to err on the side of caution.

I'll resubmit the MP...

Cheers,

James.

Scott James Remnant (scott) wrote : Posted in a previous version of this proposal
Download full text (18.3 KiB)

str can never turn to NULL as a result of incrementing

On Tue, Aug 30, 2011 at 7:33 AM, James Hunt <email address hidden>wrote:

> James Hunt has proposed merging lp:~jamesodhunt/libnih/fix-for-bug-834813
> into lp:libnih.
>
> Requested reviews:
> Scott James Remnant (scott)
>
> For more details, see:
>
> https://code.launchpad.net/~jamesodhunt/libnih/fix-for-bug-834813/+merge/73383
>
> * ChangeLog: updated.
> * nih/string.c (nih_str_split): Fixes to avoid over-running
> input string and also returning an empty string array entry
> when repeat is true (LP: #834813).
> * nih/tests/test_string.c (test_str_split): Added a lot of new
> tests for nih_str_split().
>
> --
>
> https://code.launchpad.net/~jamesodhunt/libnih/fix-for-bug-834813/+merge/73383
> You are requested to review the proposed merge of
> lp:~jamesodhunt/libnih/fix-for-bug-834813 into lp:libnih.
>
> === modified file 'ChangeLog'
> --- ChangeLog 2011-08-26 18:31:43 +0000
> +++ ChangeLog 2011-08-30 14:33:16 +0000
> @@ -1,3 +1,4 @@
> +<<<<<<< TREE
> 2011-08-26 James Hunt <email address hidden>
>
> * nih/io.c (nih_io_select_fds): Ensure number of fds being managed
> @@ -6,6 +7,16 @@
> * nih/config.c, nih/error.h, nih/io.c, nih/test_files.h: Correct
> typos in comments.
>
> +=======
> +2011-08-30 James Hunt <email address hidden>
> +
> + * nih/string.c (nih_str_split): Fixes to avoid over-running
> + input string and also returning an empty string array entry
> + when repeat is true (LP: #834813).
> + * nih/tests/test_string.c (test_str_split): Added a lot of new
> + tests for nih_str_split().
> +
> +>>>>>>> MERGE-SOURCE
> 2011-06-20 James Hunt <email address hidden>
>
> * nih/watch.c (nih_watch_handle): Handle non-directory watches;
>
> === modified file 'nih/string.c'
> --- nih/string.c 2009-06-23 09:29:37 +0000
> +++ nih/string.c 2011-08-30 14:33:16 +0000
> @@ -403,17 +403,29 @@
>
> while (*str) {
> const char *ptr;
> + size_t toklen;
>
> - /* Skip initial delimiters */
> - while (repeat && strchr (delim, *str))
> + /* Skip initial delimiters taking care not to walk
> + * beyond the end of the string
> + */
> + while (repeat && str && *str && strchr (delim, *str))
> str++;
>
> /* Find the end of the token */
> ptr = str;
> - while (*str && (! strchr (delim, *str)))
> + while (str && *str && (! strchr (delim, *str)))
> str++;
>
> - if (! nih_str_array_addn (&array, parent, &len,
> + toklen = str - ptr;
> +
> + /* Don't create an empty string array element in repeat
> + * mode if there is no token (as a result of a
> + * duplicated delimiter character).
> + */
> + if (repeat && !toklen)
> + continue;
> +
> + if (str && ! nih_str_array_addn (&array, parent, &len,
> ptr, str ...

Scott James Remnant (scott) wrote : Posted in a previous version of this proposal
Download full text (19.0 KiB)

Last comments are all nits (I promise!)

ChangeLog has merge markers in the review diff;

and today is now the 31st, so this needs a ChangeLog header of its own.

- /* Skip initial delimiters */
- while (repeat && strchr (delim, *str))
+ /* Skip initial delimiters taking care not to walk
+ * beyond the end of the string
+ */

There's no need to change this comment, leave it as it is.

+ toklen = str - ptr;
+
+ /* Don't create an empty string array element in repeat
+ * mode if there is no token (as a result of a
+ * duplicated delimiter character).
+ */
+ if (repeat && !toklen)
+ continue;
+

Calculating the length of the token and checking it is completely
unnecessary. A much better check would be:

  if (repeat && (str == ptr))

This is much clearer that you mean "if we're repeating, and the end of the
string is the start"

On Wed, Aug 31, 2011 at 10:02 AM, James Hunt <email address hidden>wrote:

> James Hunt has proposed merging lp:~jamesodhunt/libnih/fix-for-bug-834813
> into lp:libnih.
>
> Requested reviews:
> Scott James Remnant (scott)
>
> For more details, see:
>
> https://code.launchpad.net/~jamesodhunt/libnih/fix-for-bug-834813/+merge/73560
>
> Take 3... :-)
>
> * ChangeLog: updated.
> * nih/string.c (nih_str_split): Fixes to avoid over-running
> input string and also returning an empty string array entry
> when repeat is true (LP: #834813).
> * nih/tests/test_string.c (test_str_split): Added a lot of new
> tests for nih_str_split().
>
> --
>
> https://code.launchpad.net/~jamesodhunt/libnih/fix-for-bug-834813/+merge/73560
> You are requested to review the proposed merge of
> lp:~jamesodhunt/libnih/fix-for-bug-834813 into lp:libnih.
>
> === modified file 'ChangeLog'
> --- ChangeLog 2011-08-26 18:31:43 +0000
> +++ ChangeLog 2011-08-31 17:02:23 +0000
> @@ -1,3 +1,4 @@
> +<<<<<<< TREE
> 2011-08-26 James Hunt <email address hidden>
>
> * nih/io.c (nih_io_select_fds): Ensure number of fds being managed
> @@ -6,6 +7,16 @@
> * nih/config.c, nih/error.h, nih/io.c, nih/test_files.h: Correct
> typos in comments.
>
> +=======
> +2011-08-31 James Hunt <email address hidden>
> +
> + * nih/string.c (nih_str_split): Fixes to avoid over-running
> + input string and also returning an empty string array entry
> + when repeat is true (LP: #834813).
> + * nih/tests/test_string.c (test_str_split): Added a lot of new
> + tests for nih_str_split().
> +
> +>>>>>>> MERGE-SOURCE
> 2011-06-20 James Hunt <email address hidden>
>
> * nih/watch.c (nih_watch_handle): Handle non-directory watches;
>
> === modified file 'nih/string.c'
> --- nih/string.c 2009-06-23 09:29:37 +0000
> +++ nih/string.c 2011-08-31 17:02:23 +0000
> @@ -403,9 +403,12 @@
>
> while (*str) {
> const char *ptr;
> + size_t toklen;
>
> - /* Skip initial delimiters */
> - while (repeat && strchr (delim, *str))
> + /* Skip initi...

Scott James Remnant (scott) wrote : Posted in a previous version of this proposal

On Tue, Aug 30, 2011 at 7:33 AM, James Hunt <email address hidden>wrote:

> Firstly, I've raised a bug on strchr(3) and memchr(3) since they do not
> currently specify the behaviour should the char to search for be '\0':
>
> https://bugzilla.kernel.org/show_bug.cgi?id=42042
>
>
Interestingly the OS X man pages do specify:

     The strchr() function locates the first occurrence of c (converted to a
     char) in the string pointed to by s. The terminating null character is
     considered to be part of the string; therefore if c is `\0', the func-
     tions locate the terminating `\0'.

Scott

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2011-08-26 18:31:43 +0000
3+++ ChangeLog 2011-08-31 19:05:23 +0000
4@@ -1,3 +1,11 @@
5+2011-08-31 James Hunt <james.hunt@ubuntu.com>
6+
7+ * nih/string.c (nih_str_split): Fixes to avoid over-running
8+ input string and also returning an empty string array entry
9+ when repeat is true (LP: #834813).
10+ * nih/tests/test_string.c (test_str_split): Added a lot of new
11+ tests for nih_str_split().
12+
13 2011-08-26 James Hunt <james.hunt@ubuntu.com>
14
15 * nih/io.c (nih_io_select_fds): Ensure number of fds being managed
16
17=== modified file 'nih/string.c'
18--- nih/string.c 2009-06-23 09:29:37 +0000
19+++ nih/string.c 2011-08-31 19:05:23 +0000
20@@ -405,7 +405,7 @@
21 const char *ptr;
22
23 /* Skip initial delimiters */
24- while (repeat && strchr (delim, *str))
25+ while (repeat && *str && strchr (delim, *str))
26 str++;
27
28 /* Find the end of the token */
29@@ -413,6 +413,13 @@
30 while (*str && (! strchr (delim, *str)))
31 str++;
32
33+ /* Don't create an empty string array element in repeat
34+ * mode if there is no token (as a result of a
35+ * duplicated delimiter character).
36+ */
37+ if (repeat && (str == ptr))
38+ continue;
39+
40 if (! nih_str_array_addn (&array, parent, &len,
41 ptr, str - ptr)) {
42 nih_free (array);
43
44=== modified file 'nih/tests/test_string.c'
45--- nih/tests/test_string.c 2009-11-28 20:25:03 +0000
46+++ nih/tests/test_string.c 2011-08-31 19:05:23 +0000
47@@ -619,6 +619,215 @@
48 nih_free (array);
49 }
50
51+ TEST_FEATURE ("with no repeat and multiple identical delimiter "
52+ "characters at string start");
53+ TEST_ALLOC_FAIL {
54+ array = nih_str_split (NULL, "\t\tthis is a test", " \t", FALSE);
55+
56+ if (test_alloc_failed) {
57+ TEST_EQ_P (array, NULL);
58+ continue;
59+ }
60+
61+ TEST_ALLOC_SIZE (array, sizeof (char *) * 7);
62+ for (i = 0; i < 6; i++)
63+ TEST_ALLOC_PARENT (array[i], array);
64+
65+ TEST_EQ_STR (array[0], "");
66+ TEST_EQ_STR (array[1], "");
67+ TEST_EQ_STR (array[2], "this");
68+ TEST_EQ_STR (array[3], "is");
69+ TEST_EQ_STR (array[4], "a");
70+ TEST_EQ_STR (array[5], "test");
71+ TEST_EQ_P (array[6], NULL);
72+
73+ nih_free (array);
74+ }
75+
76+ TEST_FEATURE ("with no repeat and multiple different delimiter "
77+ "characters at string start");
78+ TEST_ALLOC_FAIL {
79+ array = nih_str_split (NULL, " \tthis is a test", " \t", FALSE);
80+
81+ if (test_alloc_failed) {
82+ TEST_EQ_P (array, NULL);
83+ continue;
84+ }
85+
86+ TEST_ALLOC_SIZE (array, sizeof (char *) * 7);
87+ for (i = 0; i < 6; i++)
88+ TEST_ALLOC_PARENT (array[i], array);
89+
90+ TEST_EQ_STR (array[0], "");
91+ TEST_EQ_STR (array[1], "");
92+ TEST_EQ_STR (array[2], "this");
93+ TEST_EQ_STR (array[3], "is");
94+ TEST_EQ_STR (array[4], "a");
95+ TEST_EQ_STR (array[5], "test");
96+ TEST_EQ_P (array[6], NULL);
97+
98+ nih_free (array);
99+ }
100+
101+ TEST_FEATURE ("with no repeat and multiple identical delimiter "
102+ "characters within string");
103+ TEST_ALLOC_FAIL {
104+ array = nih_str_split (NULL, "this is a\t\ttest", " \t", FALSE);
105+
106+ if (test_alloc_failed) {
107+ TEST_EQ_P (array, NULL);
108+ continue;
109+ }
110+
111+ TEST_ALLOC_SIZE (array, sizeof (char *) * 8);
112+ for (i = 0; i < 7; i++)
113+ TEST_ALLOC_PARENT (array[i], array);
114+
115+ TEST_EQ_STR (array[0], "this");
116+ TEST_EQ_STR (array[1], "is");
117+ TEST_EQ_STR (array[2], "");
118+ TEST_EQ_STR (array[3], "");
119+ TEST_EQ_STR (array[4], "a");
120+ TEST_EQ_STR (array[5], "");
121+ TEST_EQ_STR (array[6], "test");
122+ TEST_EQ_P (array[7], NULL);
123+
124+ nih_free (array);
125+ }
126+
127+ TEST_FEATURE ("with no repeat and multiple different delimiter "
128+ "characters within string");
129+ TEST_ALLOC_FAIL {
130+ array = nih_str_split (NULL, "this is \n\ta\ttest", " \t\n", FALSE);
131+
132+ if (test_alloc_failed) {
133+ TEST_EQ_P (array, NULL);
134+ continue;
135+ }
136+
137+ TEST_ALLOC_SIZE (array, sizeof (char *) * 7);
138+ for (i = 0; i < 6; i++)
139+ TEST_ALLOC_PARENT (array[i], array);
140+
141+ TEST_EQ_STR (array[0], "this");
142+ TEST_EQ_STR (array[1], "is");
143+ TEST_EQ_STR (array[2], "");
144+ TEST_EQ_STR (array[3], "");
145+ TEST_EQ_STR (array[4], "a");
146+ TEST_EQ_STR (array[5], "test");
147+ TEST_EQ_P (array[6], NULL);
148+
149+ nih_free (array);
150+ }
151+
152+ TEST_FEATURE ("with no repeat and multiple identical delimiter "
153+ "characters at string end");
154+ TEST_ALLOC_FAIL {
155+ array = nih_str_split (NULL, "this is a test ", " \t", FALSE);
156+
157+ if (test_alloc_failed) {
158+ TEST_EQ_P (array, NULL);
159+ continue;
160+ }
161+
162+ TEST_ALLOC_SIZE (array, sizeof (char *) * 6);
163+ for (i = 0; i < 5; i++)
164+ TEST_ALLOC_PARENT (array[i], array);
165+
166+ TEST_EQ_STR (array[0], "this");
167+ TEST_EQ_STR (array[1], "is");
168+ TEST_EQ_STR (array[2], "a");
169+ TEST_EQ_STR (array[3], "test");
170+ TEST_EQ_STR (array[4], "");
171+ TEST_EQ_P (array[5], NULL);
172+
173+ nih_free (array);
174+ }
175+
176+ TEST_FEATURE ("with no repeat and multiple different delimiter "
177+ "characters at string end");
178+ TEST_ALLOC_FAIL {
179+ array = nih_str_split (NULL, "this is a test \t", " \t", FALSE);
180+
181+ if (test_alloc_failed) {
182+ TEST_EQ_P (array, NULL);
183+ continue;
184+ }
185+
186+ TEST_ALLOC_SIZE (array, sizeof (char *) * 6);
187+ for (i = 0; i < 5; i++)
188+ TEST_ALLOC_PARENT (array[i], array);
189+
190+ TEST_EQ_STR (array[0], "this");
191+ TEST_EQ_STR (array[1], "is");
192+ TEST_EQ_STR (array[2], "a");
193+ TEST_EQ_STR (array[3], "test");
194+ TEST_EQ_STR (array[4], "");
195+ TEST_EQ_P (array[5], NULL);
196+
197+ nih_free (array);
198+ }
199+
200+ TEST_FEATURE ("with no repeat and multiple identical delimiter "
201+ "characters at beginning, middle and end of string");
202+ TEST_ALLOC_FAIL {
203+ array = nih_str_split (NULL, " this is\n\n\na test\t\t\t", " \t\n", FALSE);
204+
205+ if (test_alloc_failed) {
206+ TEST_EQ_P (array, NULL);
207+ continue;
208+ }
209+
210+ TEST_ALLOC_SIZE (array, sizeof (char *) * 12);
211+ for (i = 0; i < 11; i++)
212+ TEST_ALLOC_PARENT (array[i], array);
213+
214+ TEST_EQ_STR (array[0], "");
215+ TEST_EQ_STR (array[1], "");
216+ TEST_EQ_STR (array[2], "");
217+ TEST_EQ_STR (array[3], "this");
218+ TEST_EQ_STR (array[4], "is");
219+ TEST_EQ_STR (array[5], "");
220+ TEST_EQ_STR (array[6], "");
221+ TEST_EQ_STR (array[7], "a");
222+ TEST_EQ_STR (array[8], "test");
223+ TEST_EQ_STR (array[9], "");
224+ TEST_EQ_STR (array[10], "");
225+ TEST_EQ_P (array[11], NULL);
226+
227+ nih_free (array);
228+ }
229+
230+ TEST_FEATURE ("with no repeat and multiple different delimiter "
231+ "characters at beginning, middle and end of string");
232+ TEST_ALLOC_FAIL {
233+ array = nih_str_split (NULL, ": \nthis is\t \n:a test:\n ", "\n :\t", FALSE);
234+
235+ if (test_alloc_failed) {
236+ TEST_EQ_P (array, NULL);
237+ continue;
238+ }
239+
240+ TEST_ALLOC_SIZE (array, sizeof (char *) * 13);
241+ for (i = 0; i < 12; i++)
242+ TEST_ALLOC_PARENT (array[i], array);
243+
244+ TEST_EQ_STR (array[0], "");
245+ TEST_EQ_STR (array[1], "");
246+ TEST_EQ_STR (array[2], "");
247+ TEST_EQ_STR (array[3], "this");
248+ TEST_EQ_STR (array[4], "is");
249+ TEST_EQ_STR (array[5], "");
250+ TEST_EQ_STR (array[6], "");
251+ TEST_EQ_STR (array[7], "");
252+ TEST_EQ_STR (array[8], "a");
253+ TEST_EQ_STR (array[9], "test");
254+ TEST_EQ_STR (array[10], "");
255+ TEST_EQ_STR (array[11], "");
256+ TEST_EQ_P (array[12], NULL);
257+
258+ nih_free (array);
259+ }
260
261 /* Check that we can split a string treating multiple consecutive
262 * matching characters as a single separator to be skipped.
263@@ -645,6 +854,177 @@
264 nih_free (array);
265 }
266
267+ /* Check that we can split a string containing multiple
268+ * occurences of one of the delimiter characters at the
269+ * beginning of the string.
270+ */
271+ TEST_FEATURE ("with repeat and multiple identical adjacent delimiter characters at string start");
272+ TEST_ALLOC_FAIL {
273+ array = nih_str_split (NULL, "\n\nhello", " \t\r\n", TRUE);
274+
275+ if (test_alloc_failed) {
276+ TEST_EQ_P (array, NULL);
277+ continue;
278+ }
279+
280+ TEST_ALLOC_SIZE (array, sizeof (char *) * 2);
281+ for (i = 0; i < 1; i++)
282+ TEST_ALLOC_PARENT (array[i], array);
283+
284+ TEST_EQ_STR (array[0], "hello");
285+ TEST_EQ_P (array[1], NULL);
286+
287+ nih_free (array);
288+ }
289+
290+ TEST_FEATURE ("with repeat and multiple different adjacent delimiter characters at string start");
291+ TEST_ALLOC_FAIL {
292+ array = nih_str_split (NULL, "\n\r hello", " \t\r\n", TRUE);
293+
294+ if (test_alloc_failed) {
295+ TEST_EQ_P (array, NULL);
296+ continue;
297+ }
298+
299+ TEST_ALLOC_SIZE (array, sizeof (char *) * 2);
300+ for (i = 0; i < 1; i++)
301+ TEST_ALLOC_PARENT (array[i], array);
302+
303+ TEST_EQ_STR (array[0], "hello");
304+ TEST_EQ_P (array[1], NULL);
305+
306+ nih_free (array);
307+ }
308+
309+ TEST_FEATURE ("with repeat and multiple identical adjacent delimiter "
310+ "characters within string");
311+ TEST_ALLOC_FAIL {
312+ array = nih_str_split (NULL, "hello\n\rworld", " \t\n\r", TRUE);
313+
314+ if (test_alloc_failed) {
315+ TEST_EQ_P (array, NULL);
316+ continue;
317+ }
318+
319+ TEST_ALLOC_SIZE (array, sizeof (char *) * 3);
320+ for (i = 0; i < 2; i++)
321+ TEST_ALLOC_PARENT (array[i], array);
322+
323+ TEST_EQ_STR (array[0], "hello");
324+ TEST_EQ_STR (array[1], "world");
325+ TEST_EQ_P (array[2], NULL);
326+
327+ nih_free (array);
328+ }
329+
330+ TEST_FEATURE ("with repeat and multiple different adjacent delimiter "
331+ "characters within string");
332+ TEST_ALLOC_FAIL {
333+ array = nih_str_split (NULL, "hello\n\r\tworld", " \t\n\r", TRUE);
334+
335+ if (test_alloc_failed) {
336+ TEST_EQ_P (array, NULL);
337+ continue;
338+ }
339+
340+ TEST_ALLOC_SIZE (array, sizeof (char *) * 3);
341+ for (i = 0; i < 2; i++)
342+ TEST_ALLOC_PARENT (array[i], array);
343+
344+ TEST_EQ_STR (array[0], "hello");
345+ TEST_EQ_STR (array[1], "world");
346+ TEST_EQ_P (array[2], NULL);
347+
348+ nih_free (array);
349+ }
350+
351+ TEST_FEATURE ("with repeat and multiple identical adjacent delimiter "
352+ "characters at string end");
353+ TEST_ALLOC_FAIL {
354+ array = nih_str_split (NULL, "hello\n\n\n\n\n\n\n", " \t\r\n", TRUE);
355+
356+ if (test_alloc_failed) {
357+ TEST_EQ_P (array, NULL);
358+ continue;
359+ }
360+
361+ TEST_ALLOC_SIZE (array, sizeof (char *) * 2);
362+ for (i = 0; i < 1; i++)
363+ TEST_ALLOC_PARENT (array[i], array);
364+
365+ TEST_EQ_STR (array[0], "hello");
366+ TEST_EQ_P (array[1], NULL);
367+
368+ nih_free (array);
369+ }
370+
371+ TEST_FEATURE ("with repeat and multiple different adjacent delimiter "
372+ "characters at string end");
373+ TEST_ALLOC_FAIL {
374+ array = nih_str_split (NULL, "hello \r\t\r\t\n ", " \t\r\n", TRUE);
375+
376+ if (test_alloc_failed) {
377+ TEST_EQ_P (array, NULL);
378+ continue;
379+ }
380+
381+ TEST_ALLOC_SIZE (array, sizeof (char *) * 2);
382+ for (i = 0; i < 1; i++)
383+ TEST_ALLOC_PARENT (array[i], array);
384+
385+ TEST_EQ_STR (array[0], "hello");
386+ TEST_EQ_P (array[1], NULL);
387+
388+ nih_free (array);
389+ }
390+
391+ TEST_FEATURE ("with repeat and multiple identical adjacent delimiter "
392+ "characters at beginning, middle and end of string");
393+ TEST_ALLOC_FAIL {
394+ array = nih_str_split (NULL,
395+ " hello\n\n\n, world\n\n\n",
396+ "\r\t\n ", TRUE);
397+
398+ if (test_alloc_failed) {
399+ TEST_EQ_P (array, NULL);
400+ continue;
401+ }
402+
403+ TEST_ALLOC_SIZE (array, sizeof (char *) * 4);
404+ for (i = 0; i < 3; i++)
405+ TEST_ALLOC_PARENT (array[i], array);
406+
407+ TEST_EQ_STR (array[0], "hello");
408+ TEST_EQ_STR (array[1], ",");
409+ TEST_EQ_STR (array[2], "world");
410+ TEST_EQ_P (array[3], NULL);
411+
412+ nih_free (array);
413+ }
414+
415+ TEST_FEATURE ("with repeat and multiple different adjacent delimiter "
416+ "characters at beginning, middle and end of string");
417+ TEST_ALLOC_FAIL {
418+ array = nih_str_split (NULL,
419+ "\n \r\thello\n\n\r , \n\t\rworld\t \r\n \n",
420+ " \t\n\r", TRUE);
421+
422+ if (test_alloc_failed) {
423+ TEST_EQ_P (array, NULL);
424+ continue;
425+ }
426+
427+ TEST_ALLOC_SIZE (array, sizeof (char *) * 4);
428+ for (i = 0; i < 3; i++)
429+ TEST_ALLOC_PARENT (array[i], array);
430+
431+ TEST_EQ_STR (array[0], "hello");
432+ TEST_EQ_STR (array[1], ",");
433+ TEST_EQ_STR (array[2], "world");
434+ TEST_EQ_P (array[3], NULL);
435+
436+ nih_free (array);
437+ }
438
439 /* Check that we can give an empty string, and end up with a
440 * one-element array that only contains a NULL pointer.

Subscribers

People subscribed via source and target branches