Merge lp:~jamesodhunt/libnih/fix-for-bug-834813 into lp:libnih
- fix-for-bug-834813
- Merge into trunk
Status: | Superseded | ||||
---|---|---|---|---|---|
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Scott James Remnant | Pending | ||
Review via email: mp+73573@code.launchpad.net |
This proposal supersedes a proposal from 2011-08-31.
This proposal has been superseded by a proposal from 2011-08-31.
Commit message
Description of the change
Sigh... Re-merged with no conflicts this time :)
* 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/
tests for nih_str_split().
Scott James Remnant (scott) wrote : Posted in a previous version of this proposal | # |
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:/
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 | # |
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:/
>
> * 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/
> tests for nih_str_split().
>
> --
>
> https:/
> 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_
> @@ -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/
> + 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 | # |
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:/
>
> 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/
> tests for nih_str_split().
>
> --
>
> https:/
> 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_
> @@ -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/
> + 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:/
>
>
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
- 1053. By James Hunt
-
* 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().
Unmerged revisions
Preview Diff
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2011-08-26 18:31:43 +0000 |
3 | +++ ChangeLog 2011-08-31 19:05:24 +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:24 +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:24 +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. |
"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