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