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