1 /*
2  * Split narrow string functions
3  *
4  * Copyright (C) 2008-2020, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <memory.h>
24 #include <narrow_string.h>
25 #include <types.h>
26 
27 #include "libcsplit_libcerror.h"
28 #include "libcsplit_narrow_split_string.h"
29 #include "libcsplit_types.h"
30 
31 /* Creates a split string
32  * Make sure the value split_string is referencing, is set to NULL
33  * Returns 1 if successful or -1 on error
34  */
libcsplit_narrow_split_string_initialize(libcsplit_narrow_split_string_t ** split_string,const char * string,size_t string_size,int number_of_segments,libcerror_error_t ** error)35 int libcsplit_narrow_split_string_initialize(
36      libcsplit_narrow_split_string_t **split_string,
37      const char *string,
38      size_t string_size,
39      int number_of_segments,
40      libcerror_error_t **error )
41 {
42 	libcsplit_internal_narrow_split_string_t *internal_split_string = NULL;
43 	static char *function                                           = "libcsplit_narrow_split_string_initialize";
44 
45 	if( split_string == NULL )
46 	{
47 		libcerror_error_set(
48 		 error,
49 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51 		 "%s: invalid split string.",
52 		 function );
53 
54 		return( -1 );
55 	}
56 	if( *split_string != NULL )
57 	{
58 		libcerror_error_set(
59 		 error,
60 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
61 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
62 		 "%s: invalid split string value already set.",
63 		 function );
64 
65 		return( -1 );
66 	}
67 	if( number_of_segments < 0 )
68 	{
69 		libcerror_error_set(
70 		 error,
71 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
72 		 LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
73 		 "%s: invalid number of segments less than zero.",
74 		 function );
75 
76 		return( -1 );
77 	}
78 	internal_split_string = memory_allocate_structure(
79 			         libcsplit_internal_narrow_split_string_t );
80 
81 	if( internal_split_string == NULL )
82 	{
83 		libcerror_error_set(
84 		 error,
85 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
86 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
87 		 "%s: unable to create split string.",
88 		 function );
89 
90 		goto on_error;
91 	}
92 	if( memory_set(
93 	     internal_split_string,
94 	     0,
95 	     sizeof( libcsplit_internal_narrow_split_string_t ) ) == NULL )
96 	{
97 		libcerror_error_set(
98 		 error,
99 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
100 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
101 		 "%s: unable to clear split string.",
102 		 function );
103 
104 		memory_free(
105 		 internal_split_string );
106 
107 		return( -1 );
108 	}
109 	if( ( string != NULL )
110 	 && ( string_size > 0 ) )
111 	{
112 		internal_split_string->string = narrow_string_allocate(
113 		                                 string_size );
114 
115 		if( internal_split_string->string == NULL )
116 		{
117 			libcerror_error_set(
118 			 error,
119 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
120 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
121 			 "%s: unable to create string.",
122 			 function );
123 
124 			goto on_error;
125 		}
126 		if( memory_copy(
127 		     internal_split_string->string,
128 		     string,
129 		     sizeof( char ) * ( string_size - 1 ) ) == NULL )
130 		{
131 			libcerror_error_set(
132 			 error,
133 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
134 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
135 			 "%s: unable to copy string.",
136 			 function );
137 
138 			goto on_error;
139 		}
140 		internal_split_string->string[ string_size - 1 ] = 0;
141 		internal_split_string->string_size               = string_size;
142 	}
143 	if( number_of_segments > 0 )
144 	{
145 		internal_split_string->segments = (char **) memory_allocate(
146 		                                             sizeof( char * ) * number_of_segments );
147 
148 		if( internal_split_string->segments == NULL )
149 		{
150 			libcerror_error_set(
151 			 error,
152 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
153 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
154 			 "%s: unable to create segments.",
155 			 function );
156 
157 			goto on_error;
158 		}
159 		if( memory_set(
160 		     internal_split_string->segments,
161 		     0,
162 		     sizeof( char * ) * number_of_segments ) == NULL )
163 		{
164 			libcerror_error_set(
165 			 error,
166 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
167 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
168 			 "%s: unable to clear segments.",
169 			 function );
170 
171 			goto on_error;
172 		}
173 		internal_split_string->segment_sizes = (size_t *) memory_allocate(
174 		                                                   sizeof( size_t ) * number_of_segments );
175 
176 		if( internal_split_string->segment_sizes == NULL )
177 		{
178 			libcerror_error_set(
179 			 error,
180 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
181 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
182 			 "%s: unable to create segment sizes.",
183 			 function );
184 
185 			goto on_error;
186 		}
187 		if( memory_set(
188 		     internal_split_string->segment_sizes,
189 		     0,
190 		     sizeof( size_t ) * number_of_segments ) == NULL )
191 		{
192 			libcerror_error_set(
193 			 error,
194 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
195 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
196 			 "%s: unable to clear segment sizes.",
197 			 function );
198 
199 			goto on_error;
200 		}
201 	}
202 	internal_split_string->number_of_segments = number_of_segments;
203 
204 	*split_string = (libcsplit_narrow_split_string_t *) internal_split_string;
205 
206 	return( 1 );
207 
208 on_error:
209 	if( internal_split_string != NULL )
210 	{
211 		if( internal_split_string->segment_sizes != NULL )
212 		{
213 			memory_free(
214 			 internal_split_string->segment_sizes );
215 		}
216 		if( internal_split_string->segments != NULL )
217 		{
218 			memory_free(
219 			 internal_split_string->segments );
220 		}
221 		if( internal_split_string->string != NULL )
222 		{
223 			memory_free(
224 			 internal_split_string->string );
225 		}
226 		memory_free(
227 		 internal_split_string );
228 	}
229 	return( -1 );
230 }
231 
232 /* Frees a split string
233  * Returns 1 if successful or -1 on error
234  */
libcsplit_narrow_split_string_free(libcsplit_narrow_split_string_t ** split_string,libcerror_error_t ** error)235 int libcsplit_narrow_split_string_free(
236      libcsplit_narrow_split_string_t **split_string,
237      libcerror_error_t **error )
238 {
239 	libcsplit_internal_narrow_split_string_t *internal_split_string = NULL;
240 	static char *function                                           = "libcsplit_narrow_split_string_free";
241 
242 	if( split_string == NULL )
243 	{
244 		libcerror_error_set(
245 		 error,
246 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
247 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
248 		 "%s: invalid split string.",
249 		 function );
250 
251 		return( -1 );
252 	}
253 	if( *split_string != NULL )
254 	{
255 		internal_split_string = (libcsplit_internal_narrow_split_string_t *) *split_string;
256 		*split_string         = NULL;
257 
258 		if( internal_split_string->string != NULL )
259 		{
260 			memory_free(
261 			 internal_split_string->string );
262 		}
263 		if( internal_split_string->segments != NULL )
264 		{
265 			memory_free(
266 			 internal_split_string->segments );
267 		}
268 		if( internal_split_string->segment_sizes != NULL )
269 		{
270 			memory_free(
271 			 internal_split_string->segment_sizes );
272 		}
273 		memory_free(
274 		 internal_split_string );
275 	}
276 	return( 1 );
277 }
278 
279 /* Retrieves the string
280  * Returns 1 if successful or -1 on error
281  */
libcsplit_narrow_split_string_get_string(libcsplit_narrow_split_string_t * split_string,char ** string,size_t * string_size,libcerror_error_t ** error)282 int libcsplit_narrow_split_string_get_string(
283      libcsplit_narrow_split_string_t *split_string,
284      char **string,
285      size_t *string_size,
286      libcerror_error_t **error )
287 {
288 	libcsplit_internal_narrow_split_string_t *internal_split_string = NULL;
289 	static char *function                                           = "libcsplit_narrow_split_string_get_string";
290 
291 	if( split_string == NULL )
292 	{
293 		libcerror_error_set(
294 		 error,
295 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
296 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
297 		 "%s: invalid split string.",
298 		 function );
299 
300 		return( -1 );
301 	}
302 	internal_split_string = (libcsplit_internal_narrow_split_string_t *) split_string;
303 
304 	if( string == NULL )
305 	{
306 		libcerror_error_set(
307 		 error,
308 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
309 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
310 		 "%s: invalid string.",
311 		 function );
312 
313 		return( -1 );
314 	}
315 	if( string_size == NULL )
316 	{
317 		libcerror_error_set(
318 		 error,
319 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
320 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
321 		 "%s: invalid string size.",
322 		 function );
323 
324 		return( -1 );
325 	}
326 	*string      = internal_split_string->string;
327 	*string_size = internal_split_string->string_size;
328 
329 	return( 1 );
330 }
331 
332 /* Retrieves the number of segments
333  * Returns 1 if successful or -1 on error
334  */
libcsplit_narrow_split_string_get_number_of_segments(libcsplit_narrow_split_string_t * split_string,int * number_of_segments,libcerror_error_t ** error)335 int libcsplit_narrow_split_string_get_number_of_segments(
336      libcsplit_narrow_split_string_t *split_string,
337      int *number_of_segments,
338      libcerror_error_t **error )
339 {
340 	libcsplit_internal_narrow_split_string_t *internal_split_string = NULL;
341 	static char *function                                           = "libcsplit_narrow_split_string_get_number_of_segments";
342 
343 	if( split_string == NULL )
344 	{
345 		libcerror_error_set(
346 		 error,
347 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
348 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
349 		 "%s: invalid split string.",
350 		 function );
351 
352 		return( -1 );
353 	}
354 	internal_split_string = (libcsplit_internal_narrow_split_string_t *) split_string;
355 
356 	if( number_of_segments == NULL )
357 	{
358 		libcerror_error_set(
359 		 error,
360 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
361 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
362 		 "%s: invalid number of segments.",
363 		 function );
364 
365 		return( -1 );
366 	}
367 	*number_of_segments = internal_split_string->number_of_segments;
368 
369 	return( 1 );
370 }
371 
372 /* Retrieves a specific segment
373  * Returns 1 if successful or -1 on error
374  */
libcsplit_narrow_split_string_get_segment_by_index(libcsplit_narrow_split_string_t * split_string,int segment_index,char ** string_segment,size_t * string_segment_size,libcerror_error_t ** error)375 int libcsplit_narrow_split_string_get_segment_by_index(
376      libcsplit_narrow_split_string_t *split_string,
377      int segment_index,
378      char **string_segment,
379      size_t *string_segment_size,
380      libcerror_error_t **error )
381 {
382 	libcsplit_internal_narrow_split_string_t *internal_split_string = NULL;
383 	static char *function                                           = "libcsplit_narrow_split_string_get_segment_by_index";
384 
385 	if( split_string == NULL )
386 	{
387 		libcerror_error_set(
388 		 error,
389 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
390 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
391 		 "%s: invalid split string.",
392 		 function );
393 
394 		return( -1 );
395 	}
396 	internal_split_string = (libcsplit_internal_narrow_split_string_t *) split_string;
397 
398 	if( ( segment_index < 0 )
399 	 || ( segment_index >= internal_split_string->number_of_segments ) )
400 	{
401 		libcerror_error_set(
402 		 error,
403 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
404 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
405 		 "%s: invalid segment index value out of bounds.",
406 		 function );
407 
408 		return( -1 );
409 	}
410 	if( string_segment == NULL )
411 	{
412 		libcerror_error_set(
413 		 error,
414 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
415 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
416 		 "%s: invalid string segment.",
417 		 function );
418 
419 		return( -1 );
420 	}
421 	if( string_segment_size == NULL )
422 	{
423 		libcerror_error_set(
424 		 error,
425 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
426 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
427 		 "%s: invalid string segment size.",
428 		 function );
429 
430 		return( -1 );
431 	}
432 	*string_segment      = internal_split_string->segments[ segment_index ];
433 	*string_segment_size = internal_split_string->segment_sizes[ segment_index ];
434 
435 	return( 1 );
436 }
437 
438 /* Sets a specific segment
439  * Returns 1 if successful or -1 on error
440  */
libcsplit_narrow_split_string_set_segment_by_index(libcsplit_narrow_split_string_t * split_string,int segment_index,char * string_segment,size_t string_segment_size,libcerror_error_t ** error)441 int libcsplit_narrow_split_string_set_segment_by_index(
442      libcsplit_narrow_split_string_t *split_string,
443      int segment_index,
444      char *string_segment,
445      size_t string_segment_size,
446      libcerror_error_t **error )
447 {
448 	libcsplit_internal_narrow_split_string_t *internal_split_string = NULL;
449 	static char *function                                           = "libcsplit_narrow_split_string_set_segment_by_index";
450 	size_t string_segment_offset                                    = 0;
451 
452 	if( split_string == NULL )
453 	{
454 		libcerror_error_set(
455 		 error,
456 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
458 		 "%s: invalid split string.",
459 		 function );
460 
461 		return( -1 );
462 	}
463 	internal_split_string = (libcsplit_internal_narrow_split_string_t *) split_string;
464 
465 	if( ( segment_index < 0 )
466 	 || ( segment_index >= internal_split_string->number_of_segments ) )
467 	{
468 		libcerror_error_set(
469 		 error,
470 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
471 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
472 		 "%s: invalid segment index value out of bounds.",
473 		 function );
474 
475 		return( -1 );
476 	}
477 	if( string_segment_size > (size_t) SSIZE_MAX )
478 	{
479 		libcerror_error_set(
480 		 error,
481 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
482 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
483 		 "%s: invalid string segment size value exceeds maximum.",
484 		 function );
485 
486 		return( -1 );
487 	}
488 	if( string_segment == NULL )
489 	{
490 		if( string_segment_size != 0 )
491 		{
492 			libcerror_error_set(
493 			 error,
494 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
495 			 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
496 			 "%s: invalid string segment size value out of bounds.",
497 			 function );
498 
499 			return( -1 );
500 		}
501 	}
502 	else
503 	{
504 		if( string_segment < internal_split_string->string )
505 		{
506 			libcerror_error_set(
507 			 error,
508 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
509 			 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
510 			 "%s: invalid string segment value out of bounds.",
511 			 function );
512 
513 			return( -1 );
514 		}
515 		string_segment_offset = (size_t) ( string_segment - internal_split_string->string );
516 
517 		if( string_segment_offset >= internal_split_string->string_size )
518 		{
519 			libcerror_error_set(
520 			 error,
521 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
522 			 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
523 			 "%s: invalid string segment value out of bounds.",
524 			 function );
525 
526 			return( -1 );
527 		}
528 		string_segment_offset += string_segment_size;
529 
530 		if( string_segment_offset > internal_split_string->string_size )
531 		{
532 			libcerror_error_set(
533 			 error,
534 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
535 			 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
536 			 "%s: invalid string segment value out of bounds.",
537 			 function );
538 
539 			return( -1 );
540 		}
541 	}
542 	internal_split_string->segments[ segment_index ]      = string_segment;
543 	internal_split_string->segment_sizes[ segment_index ] = string_segment_size;
544 
545 	return( 1 );
546 }
547 
548