Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5Gent.c
Line
Count
Source (jump to first uncovered line)
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the COPYING file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/****************/
14
/* Module Setup */
15
/****************/
16
17
#include "H5Gmodule.h" /* This source code file is part of the H5G module */
18
19
/***********/
20
/* Headers */
21
/***********/
22
#include "H5private.h"   /* Generic Functions     */
23
#include "H5Eprivate.h"  /* Error handling        */
24
#include "H5Fprivate.h"  /* File access       */
25
#include "H5Gpkg.h"      /* Groups          */
26
#include "H5HLprivate.h" /* Local Heaps       */
27
#include "H5MMprivate.h" /* Memory management     */
28
29
/****************/
30
/* Local Macros */
31
/****************/
32
33
/******************/
34
/* Local Typedefs */
35
/******************/
36
37
/********************/
38
/* Package Typedefs */
39
/********************/
40
41
/********************/
42
/* Local Prototypes */
43
/********************/
44
45
/*********************/
46
/* Package Variables */
47
/*********************/
48
49
/*****************************/
50
/* Library Private Variables */
51
/*****************************/
52
53
/*******************/
54
/* Local Variables */
55
/*******************/
56
57
/*-------------------------------------------------------------------------
58
 * Function:    H5G__ent_decode_vec
59
 *
60
 * Purpose:     Same as H5G_ent_decode() except it does it for an array of
61
 *              symbol table entries.
62
 *
63
 * Return:      Success:        Non-negative, with *pp pointing to the first byte
64
 *                              after the last symbol.
65
 *
66
 *              Failure:        Negative
67
 *
68
 *-------------------------------------------------------------------------
69
 */
70
herr_t
71
H5G__ent_decode_vec(const H5F_t *f, const uint8_t **pp, const uint8_t *p_end, H5G_entry_t *ent, unsigned n)
72
19
{
73
19
    unsigned u;                   /* Local index variable */
74
19
    herr_t   ret_value = SUCCEED; /* Return value */
75
76
19
    FUNC_ENTER_PACKAGE
77
78
    /* check arguments */
79
19
    assert(f);
80
19
    assert(pp);
81
19
    assert(ent);
82
83
    /* decode entries */
84
116
    for (u = 0; u < n; u++) {
85
97
        if (*pp > p_end)
86
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "ran off the end of the image buffer");
87
97
        if (H5G_ent_decode(f, pp, ent + u, p_end) < 0)
88
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode");
89
97
    }
90
91
19
done:
92
19
    FUNC_LEAVE_NOAPI(ret_value)
93
19
} /* end H5G__ent_decode_vec() */
94
95
/*-------------------------------------------------------------------------
96
 * Function:    H5G_ent_decode
97
 *
98
 * Purpose:     Decodes a symbol table entry pointed to by `*pp'.
99
 *
100
 * Return:      Success:        Non-negative with *pp pointing to the first byte
101
 *                              following the symbol table entry.
102
 *
103
 *              Failure:        Negative
104
 *
105
 *-------------------------------------------------------------------------
106
 */
107
herr_t
108
H5G_ent_decode(const H5F_t *f, const uint8_t **pp, H5G_entry_t *ent, const uint8_t *p_end)
109
104
{
110
104
    const uint8_t *p_ret = *pp;
111
104
    uint32_t       tmp;
112
104
    herr_t         ret_value = SUCCEED; /* Return value */
113
114
104
    FUNC_ENTER_NOAPI(FAIL)
115
116
    /* check arguments */
117
104
    assert(f);
118
104
    assert(pp);
119
104
    assert(ent);
120
121
104
    if (H5_IS_BUFFER_OVERFLOW(*pp, ent->name_off, p_end))
122
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "image pointer is out of bounds");
123
124
    /* decode header */
125
104
    H5F_DECODE_LENGTH(f, *pp, ent->name_off);
126
127
104
    if (H5_IS_BUFFER_OVERFLOW(*pp, H5F_SIZEOF_ADDR(f) + sizeof(uint32_t), p_end))
128
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "image pointer is out of bounds");
129
130
104
    H5F_addr_decode(f, pp, &(ent->header));
131
104
    UINT32DECODE(*pp, tmp);
132
104
    *pp += 4; /*reserved*/
133
134
104
    if (H5_IS_BUFFER_OVERFLOW(*pp, 1, p_end))
135
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "image pointer is out of bounds");
136
137
104
    ent->type = (H5G_cache_type_t)tmp;
138
139
    /* decode scratch-pad */
140
104
    switch (ent->type) {
141
71
        case H5G_NOTHING_CACHED:
142
71
            break;
143
144
31
        case H5G_CACHED_STAB:
145
31
            assert(2 * H5F_SIZEOF_ADDR(f) <= H5G_SIZEOF_SCRATCH);
146
31
            if (H5_IS_BUFFER_OVERFLOW(*pp, H5F_SIZEOF_ADDR(f) * 2, p_end))
147
0
                HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "image pointer is out of bounds");
148
31
            H5F_addr_decode(f, pp, &(ent->cache.stab.btree_addr));
149
31
            H5F_addr_decode(f, pp, &(ent->cache.stab.heap_addr));
150
31
            break;
151
152
2
        case H5G_CACHED_SLINK:
153
2
            if (H5_IS_BUFFER_OVERFLOW(*pp, sizeof(uint32_t), p_end))
154
0
                HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "image pointer is out of bounds");
155
2
            UINT32DECODE(*pp, ent->cache.slink.lval_offset);
156
2
            break;
157
158
0
        case H5G_CACHED_ERROR:
159
0
        case H5G_NCACHED:
160
0
        default:
161
0
            HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unknown symbol table entry cache type");
162
104
    } /* end switch */
163
164
104
    *pp = p_ret + H5G_SIZEOF_ENTRY_FILE(f);
165
166
104
done:
167
104
    FUNC_LEAVE_NOAPI(ret_value)
168
104
} /* end H5G_ent_decode() */
169
170
/*-------------------------------------------------------------------------
171
 * Function:    H5G__ent_encode_vec
172
 *
173
 * Purpose:     Same as H5G_ent_encode() except it does it for an array of
174
 *              symbol table entries.
175
 *
176
 * Return:      Success:        Non-negative, with *pp pointing to the first byte
177
 *                              after the last symbol.
178
 *
179
 *              Failure:        Negative
180
 *
181
 *-------------------------------------------------------------------------
182
 */
183
herr_t
184
H5G__ent_encode_vec(const H5F_t *f, uint8_t **pp, const H5G_entry_t *ent, unsigned n)
185
0
{
186
0
    unsigned u;                   /* Local index variable */
187
0
    herr_t   ret_value = SUCCEED; /* Return value */
188
189
0
    FUNC_ENTER_PACKAGE
190
191
    /* check arguments */
192
0
    assert(f);
193
0
    assert(pp);
194
0
    assert(ent);
195
196
    /* encode entries */
197
0
    for (u = 0; u < n; u++)
198
0
        if (H5G_ent_encode(f, pp, ent + u) < 0)
199
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't encode");
200
201
0
done:
202
0
    FUNC_LEAVE_NOAPI(ret_value)
203
0
} /* H5G__ent_encode_vec() */
204
205
/*-------------------------------------------------------------------------
206
 * Function:    H5G_ent_encode
207
 *
208
 * Purpose:     Encodes the specified symbol table entry into the buffer
209
 *              pointed to by *pp.
210
 *
211
 * Return:      Success:        Non-negative, with *pp pointing to the first byte
212
 *                              after the symbol table entry.
213
 *
214
 *              Failure:        Negative
215
 *
216
 *-------------------------------------------------------------------------
217
 */
218
herr_t
219
H5G_ent_encode(const H5F_t *f, uint8_t **pp, const H5G_entry_t *ent)
220
0
{
221
0
    uint8_t *p_ret     = *pp + H5G_SIZEOF_ENTRY_FILE(f);
222
0
    herr_t   ret_value = SUCCEED; /* Return value */
223
224
0
    FUNC_ENTER_NOAPI(FAIL)
225
226
    /* check arguments */
227
0
    assert(f);
228
0
    assert(pp);
229
230
    /* Check for actual entry to encode */
231
0
    if (ent) {
232
        /* encode header */
233
0
        H5F_ENCODE_LENGTH(f, *pp, ent->name_off);
234
0
        H5F_addr_encode(f, pp, ent->header);
235
0
        UINT32ENCODE(*pp, ent->type);
236
0
        UINT32ENCODE(*pp, 0); /*reserved*/
237
238
        /* encode scratch-pad */
239
0
        switch (ent->type) {
240
0
            case H5G_NOTHING_CACHED:
241
0
                break;
242
243
0
            case H5G_CACHED_STAB:
244
0
                assert(2 * H5F_SIZEOF_ADDR(f) <= H5G_SIZEOF_SCRATCH);
245
0
                H5F_addr_encode(f, pp, ent->cache.stab.btree_addr);
246
0
                H5F_addr_encode(f, pp, ent->cache.stab.heap_addr);
247
0
                break;
248
249
0
            case H5G_CACHED_SLINK:
250
0
                UINT32ENCODE(*pp, ent->cache.slink.lval_offset);
251
0
                break;
252
253
0
            case H5G_CACHED_ERROR:
254
0
            case H5G_NCACHED:
255
0
            default:
256
0
                HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unknown symbol table entry cache type");
257
0
        } /* end switch */
258
0
    }     /* end if */
259
0
    else {
260
0
        H5F_ENCODE_LENGTH(f, *pp, 0);
261
0
        H5F_addr_encode(f, pp, HADDR_UNDEF);
262
0
        UINT32ENCODE(*pp, H5G_NOTHING_CACHED);
263
0
        UINT32ENCODE(*pp, 0); /*reserved*/
264
0
    }                         /* end else */
265
266
    /* fill with zero */
267
0
    if (*pp < p_ret)
268
0
        memset(*pp, 0, (size_t)(p_ret - *pp));
269
0
    *pp = p_ret;
270
271
0
done:
272
0
    FUNC_LEAVE_NOAPI(ret_value)
273
0
} /* end H5G_ent_encode() */
274
275
/*-------------------------------------------------------------------------
276
 * Function:    H5G__ent_copy
277
 *
278
 * Purpose:     Do a deep copy of symbol table entries
279
 *
280
 * Return:  Success:  Non-negative
281
 *    Failure:  Negative
282
 *
283
 * Notes:       'depth' parameter determines how much of the group entry
284
 *              structure we want to copy.  The values are:
285
 *                  H5_COPY_SHALLOW - Copy all the fields from the source
286
 *                      to the destination, including the user path and
287
 *                      canonical path. (Destination "takes ownership" of
288
 *                      user and canonical paths)
289
 *                  H5_COPY_DEEP - Copy all the fields from the source to
290
 *                      the destination, deep copying the user and canonical
291
 *                      paths.
292
 *
293
 *-------------------------------------------------------------------------
294
 */
295
void
296
H5G__ent_copy(H5G_entry_t *dst, H5G_entry_t *src, H5_copy_depth_t depth)
297
0
{
298
0
    FUNC_ENTER_PACKAGE_NOERR
299
300
    /* Check arguments */
301
0
    assert(src);
302
0
    assert(dst);
303
0
    assert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP);
304
305
    /* Copy the top level information */
306
0
    H5MM_memcpy(dst, src, sizeof(H5G_entry_t));
307
308
    /* Deep copy the names */
309
0
    if (depth == H5_COPY_DEEP) {
310
        /* Nothing currently */
311
0
    }
312
0
    else if (depth == H5_COPY_SHALLOW) {
313
0
        H5G__ent_reset(src);
314
0
    } /* end if */
315
316
0
    FUNC_LEAVE_NOAPI_VOID
317
0
} /* end H5G__ent_copy() */
318
319
/*-------------------------------------------------------------------------
320
 * Function:  H5G__ent_reset
321
 *
322
 * Purpose: Reset a symbol table entry to an empty state
323
 *
324
 * Return:  Success:  Non-negative
325
 *    Failure:  Negative
326
 *
327
 *-------------------------------------------------------------------------
328
 */
329
void
330
H5G__ent_reset(H5G_entry_t *ent)
331
0
{
332
0
    FUNC_ENTER_PACKAGE_NOERR
333
334
    /* Check arguments */
335
0
    assert(ent);
336
337
    /* Clear the symbol table entry to an empty state */
338
0
    memset(ent, 0, sizeof(H5G_entry_t));
339
0
    ent->header = HADDR_UNDEF;
340
341
0
    FUNC_LEAVE_NOAPI_VOID
342
0
} /* end H5G__ent_reset() */
343
344
/*-------------------------------------------------------------------------
345
 * Function:  H5G__ent_to_link
346
 *
347
 * Purpose:     Convert a symbol table entry to a link
348
 *
349
 * Return:  Non-negative on success/Negative on failure
350
 *
351
 *-------------------------------------------------------------------------
352
 */
353
herr_t
354
H5G__ent_to_link(const H5G_entry_t *ent, const H5HL_t *heap, H5O_link_t *lnk)
355
825
{
356
825
    const char *name;                /* Pointer to link name in heap */
357
825
    size_t      block_size;          /* Size of the heap block */
358
825
    bool        dup_soft  = false;   /* xstrdup the symbolic link name or not */
359
825
    herr_t      ret_value = SUCCEED; /* Return value */
360
361
825
    FUNC_ENTER_PACKAGE
362
363
    /* check arguments */
364
825
    assert(ent);
365
825
    assert(heap);
366
825
    assert(lnk);
367
368
    /* Initialize structure and set (default) common info for link */
369
825
    lnk->type         = H5L_TYPE_ERROR;
370
825
    lnk->corder_valid = false; /* Creation order not valid for this link */
371
825
    lnk->corder       = 0;
372
825
    lnk->cset         = H5F_DEFAULT_CSET;
373
825
    lnk->name         = NULL;
374
375
    /* Get the size of the heap block */
376
825
    block_size = H5HL_heap_get_size(heap);
377
378
    /* Get pointer to link's name in the heap */
379
825
    if (NULL == (name = (const char *)H5HL_offset_into(heap, ent->name_off)))
380
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbol table link name");
381
382
825
    if (NULL == (lnk->name = H5MM_strndup(name, (block_size - ent->name_off))))
383
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to duplicate link name");
384
825
    if (!*lnk->name)
385
0
        HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "invalid link name");
386
387
    /* Object is a symbolic or hard link */
388
825
    if (ent->type == H5G_CACHED_SLINK) {
389
0
        const char *s; /* Pointer to link value */
390
391
0
        if (NULL == (s = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset)))
392
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get symbolic link name");
393
394
        /* Copy the link value */
395
0
        if (NULL == (lnk->u.soft.name = H5MM_strndup(s, (block_size - ent->cache.slink.lval_offset))))
396
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to duplicate symbolic link name");
397
398
0
        dup_soft = true;
399
400
        /* Set link type */
401
0
        lnk->type = H5L_TYPE_SOFT;
402
0
    } /* end if */
403
825
    else {
404
        /* Set address of object */
405
825
        lnk->u.hard.addr = ent->header;
406
407
        /* Set link type */
408
825
        lnk->type = H5L_TYPE_HARD;
409
825
    } /* end else */
410
411
825
done:
412
825
    if (ret_value < 0) {
413
0
        if (lnk->name)
414
0
            H5MM_xfree(lnk->name);
415
0
        if (ent->type == H5G_CACHED_SLINK && dup_soft)
416
0
            H5MM_xfree(lnk->u.soft.name);
417
0
    }
418
419
825
    FUNC_LEAVE_NOAPI(ret_value)
420
825
} /* end H5G__ent_to_link() */
421
422
/*-------------------------------------------------------------------------
423
 * Function:    H5G__ent_debug
424
 *
425
 * Purpose:     Prints debugging information about a symbol table entry.
426
 *
427
 * Return:      Non-negative on success/Negative on failure
428
 *
429
 *-------------------------------------------------------------------------
430
 */
431
herr_t
432
H5G__ent_debug(const H5G_entry_t *ent, FILE *stream, int indent, int fwidth, const H5HL_t *heap)
433
0
{
434
0
    const char *lval = NULL;
435
0
    int         nested_indent, nested_fwidth;
436
437
0
    FUNC_ENTER_PACKAGE_NOERR
438
439
    /* Calculate the indent & field width values for nested information */
440
0
    nested_indent = indent + 3;
441
0
    nested_fwidth = MAX(0, fwidth - 3);
442
443
0
    fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
444
0
            "Name offset into private heap:", (unsigned long)(ent->name_off));
445
446
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Object header address:", ent->header);
447
448
0
    fprintf(stream, "%*s%-*s ", indent, "", fwidth, "Cache info type:");
449
0
    switch (ent->type) {
450
0
        case H5G_NOTHING_CACHED:
451
0
            fprintf(stream, "Nothing Cached\n");
452
0
            break;
453
454
0
        case H5G_CACHED_STAB:
455
0
            fprintf(stream, "Symbol Table\n");
456
457
0
            fprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Cached entry information:");
458
0
            fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", nested_indent, "", nested_fwidth,
459
0
                    "B-tree address:", ent->cache.stab.btree_addr);
460
461
0
            fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", nested_indent, "", nested_fwidth,
462
0
                    "Heap address:", ent->cache.stab.heap_addr);
463
0
            break;
464
465
0
        case H5G_CACHED_SLINK:
466
0
            fprintf(stream, "Symbolic Link\n");
467
0
            fprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Cached information:");
468
0
            fprintf(stream, "%*s%-*s %lu\n", nested_indent, "", nested_fwidth,
469
0
                    "Link value offset:", (unsigned long)(ent->cache.slink.lval_offset));
470
0
            if (heap) {
471
0
                lval = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset);
472
0
                fprintf(stream, "%*s%-*s %s\n", nested_indent, "", nested_fwidth,
473
0
                        "Link value:", (lval == NULL) ? "" : lval);
474
0
            } /* end if */
475
0
            else
476
0
                fprintf(stream, "%*s%-*s\n", nested_indent, "", nested_fwidth,
477
0
                        "Warning: Invalid heap address given, name not displayed!");
478
0
            break;
479
480
0
        case H5G_CACHED_ERROR:
481
0
        case H5G_NCACHED:
482
0
        default:
483
0
            fprintf(stream, "*** Unknown symbol type %d\n", ent->type);
484
0
            break;
485
0
    } /* end switch */
486
487
0
    FUNC_LEAVE_NOAPI(SUCCEED)
488
0
} /* end H5G__ent_debug() */