Coverage Report

Created: 2025-09-05 06:58

/src/libesedb/libesedb/libesedb_value_data_handle.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Value data handle functions
3
 *
4
 * Copyright (C) 2009-2024, 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 "libesedb_definitions.h"
27
#include "libesedb_libcerror.h"
28
#include "libesedb_libcnotify.h"
29
#include "libesedb_libfvalue.h"
30
#include "libesedb_value_data_handle.h"
31
#include "libesedb_unused.h"
32
33
/* Retrieves the number of value entries
34
 * Return if successful or -1 on error
35
 */
36
int libesedb_value_data_handle_read_value_entries(
37
     libfvalue_data_handle_t *data_handle,
38
     const uint8_t *data,
39
     size_t data_size,
40
     int encoding LIBESEDB_ATTRIBUTE_UNUSED,
41
     uint32_t data_flags,
42
     libcerror_error_t **error )
43
0
{
44
0
  static char *function                  = "libesedb_value_data_handle_read_value_entries";
45
0
  size_t data_offset                     = 0;
46
0
  uint16_t number_of_value_entry_offsets = 0;
47
0
  uint16_t value_16bit                   = 0;
48
0
  uint16_t value_entry_offset            = 0;
49
0
  uint16_t value_entry_offset_index      = 0;
50
0
  uint16_t value_entry_size              = 0;
51
0
  int value_entry_index                  = 0;
52
53
0
  LIBESEDB_UNREFERENCED_PARAMETER( encoding )
54
55
0
  if( data_handle == NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61
0
     "%s: invalid data handle.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
0
  if( data == NULL )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
72
0
     "%s: invalid data.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
0
  if( data_size > (size_t) UINT16_MAX )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
82
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
83
0
     "%s: invalid data size value exceeds maximum.",
84
0
     function );
85
86
0
    return( -1 );
87
0
  }
88
0
  if( ( data_flags & LIBESEDB_VALUE_FLAG_MULTI_VALUE ) != 0 )
89
0
  {
90
#if defined( HAVE_DEBUG_OUTPUT )
91
    if( libcnotify_verbose != 0 )
92
    {
93
      libcnotify_printf(
94
       "%s: multi value data:\n",
95
       function );
96
      libcnotify_print_data(
97
       data,
98
       data_size,
99
       0 );
100
    }
101
#endif
102
    /* The first 2 bytes contain the offset to the first value
103
     * there is an offset for every value
104
     * therefore first offset / 2 = the number of value entries
105
     */
106
0
    byte_stream_copy_to_uint16_little_endian(
107
0
     &( data[ data_offset ] ),
108
0
     value_16bit );
109
110
0
    data_offset += 2;
111
112
#if defined( HAVE_DEBUG_OUTPUT )
113
    if( libcnotify_verbose != 0 )
114
    {
115
      libcnotify_printf(
116
       "%s: multi value offset: %03" PRIu16 "\t: 0x%04" PRIx16 " (%" PRIu16 ")\n",
117
       function,
118
       value_entry_offset_index,
119
       value_16bit,
120
       value_16bit & 0x7fff );
121
    }
122
#endif
123
0
    value_entry_offset = value_16bit & 0x7fff;
124
125
0
    number_of_value_entry_offsets = value_entry_offset / 2;
126
127
0
    if( number_of_value_entry_offsets == 0 )
128
0
    {
129
0
      libcerror_error_set(
130
0
       error,
131
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
132
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
133
0
       "%s: missing value entries.",
134
0
       function );
135
136
0
      return( -1 );
137
0
    }
138
0
    for( value_entry_offset_index = 1;
139
0
         value_entry_offset_index < number_of_value_entry_offsets;
140
0
         value_entry_offset_index++ )
141
0
    {
142
0
      byte_stream_copy_to_uint16_little_endian(
143
0
       &( data[ data_offset ] ),
144
0
       value_16bit );
145
146
0
      data_offset += 2;
147
148
#if defined( HAVE_DEBUG_OUTPUT )
149
      if( libcnotify_verbose != 0 )
150
      {
151
        libcnotify_printf(
152
         "%s: multi value offset: %03" PRIu16 "\t: 0x%04" PRIx16 " (%" PRIu16 ")\n",
153
         function,
154
         value_entry_offset_index,
155
         value_16bit,
156
         value_16bit & 0x7fff );
157
      }
158
#endif
159
0
      value_16bit &= 0x7fff;
160
161
0
      if( value_16bit < value_entry_offset )
162
0
      {
163
0
        libcerror_error_set(
164
0
         error,
165
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
166
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
167
0
         "%s: invalid value offset: %" PRIu16 " value is smaller than previous.",
168
0
         function,
169
0
         value_entry_offset_index );
170
171
0
        return( -1 );
172
0
      }
173
0
      value_entry_size = value_16bit - value_entry_offset;
174
175
0
      if( libfvalue_data_handle_append_value_entry(
176
0
           data_handle,
177
0
           &value_entry_index,
178
0
           (size_t) value_entry_offset,
179
0
           (size_t) value_entry_size,
180
0
           error ) != 1 )
181
0
      {
182
0
        libcerror_error_set(
183
0
         error,
184
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
185
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
186
0
         "%s: unable append value entry: %" PRIu16 ".",
187
0
         function,
188
0
         value_entry_offset_index - 1 );
189
190
0
        return( -1 );
191
0
      }
192
0
      value_entry_offset = value_16bit;
193
0
    }
194
0
    value_entry_size = (uint16_t) data_size - value_entry_offset;
195
196
0
    if( libfvalue_data_handle_append_value_entry(
197
0
         data_handle,
198
0
         &value_entry_index,
199
0
         (size_t) value_entry_offset,
200
0
         (size_t) value_entry_size,
201
0
         error ) != 1 )
202
0
    {
203
0
      libcerror_error_set(
204
0
       error,
205
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
206
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
207
0
       "%s: unable append value entry: %" PRIu16 ".",
208
0
       function,
209
0
       value_entry_offset_index - 1 );
210
211
0
      return( -1 );
212
0
    }
213
#if defined( HAVE_DEBUG_OUTPUT )
214
    if( libcnotify_verbose != 0 )
215
    {
216
      libcnotify_printf(
217
       "\n" );
218
    }
219
#endif
220
0
  }
221
0
  return( 1 );
222
0
}
223