Coverage Report

Created: 2025-11-16 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib-2.80.0/glib/gerror.c
Line
Count
Source
1
/* GLIB - Library of useful routines for C programming
2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
/*
21
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22
 * file for a list of people on the GLib Team.  See the ChangeLog
23
 * files for a list of changes.  These files are distributed with
24
 * GLib at ftp://ftp.gtk.org/pub/gtk/.
25
 */
26
27
#include "config.h"
28
29
#include "gvalgrind.h"
30
#include <string.h>
31
32
#include "gerror.h"
33
34
#include "ghash.h"
35
#include "glib-init.h"
36
#include "gslice.h"
37
#include "gstrfuncs.h"
38
#include "gtestutils.h"
39
#include "gthread.h"
40
41
static GRWLock error_domain_global;
42
/* error_domain_ht must be accessed with error_domain_global
43
 * locked.
44
 */
45
static GHashTable *error_domain_ht = NULL;
46
47
void
48
g_error_init (void)
49
12
{
50
12
  error_domain_ht = g_hash_table_new (NULL, NULL);
51
12
}
52
53
typedef struct
54
{
55
  /* private_size is already aligned. */
56
  gsize private_size;
57
  GErrorInitFunc init;
58
  GErrorCopyFunc copy;
59
  GErrorClearFunc clear;
60
} ErrorDomainInfo;
61
62
/* Must be called with error_domain_global locked.
63
 */
64
static inline ErrorDomainInfo *
65
error_domain_lookup (GQuark domain)
66
25.8k
{
67
25.8k
  return g_hash_table_lookup (error_domain_ht,
68
25.8k
                              GUINT_TO_POINTER (domain));
69
25.8k
}
70
71
/* Copied from gtype.c. */
72
0
#define STRUCT_ALIGNMENT (2 * sizeof (gsize))
73
#define ALIGN_STRUCT(offset) \
74
0
      ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
75
76
static void
77
error_domain_register (GQuark            error_quark,
78
                       gsize             error_type_private_size,
79
                       GErrorInitFunc    error_type_init,
80
                       GErrorCopyFunc    error_type_copy,
81
                       GErrorClearFunc   error_type_clear)
82
0
{
83
0
  g_rw_lock_writer_lock (&error_domain_global);
84
0
  if (error_domain_lookup (error_quark) == NULL)
85
0
    {
86
0
      ErrorDomainInfo *info = g_new (ErrorDomainInfo, 1);
87
0
      info->private_size = ALIGN_STRUCT (error_type_private_size);
88
0
      info->init = error_type_init;
89
0
      info->copy = error_type_copy;
90
0
      info->clear = error_type_clear;
91
92
0
      g_hash_table_insert (error_domain_ht,
93
0
                           GUINT_TO_POINTER (error_quark),
94
0
                           info);
95
0
    }
96
0
  else
97
0
    {
98
0
      const char *name = g_quark_to_string (error_quark);
99
100
0
      g_critical ("Attempted to register an extended error domain for %s more than once", name);
101
0
    }
102
0
  g_rw_lock_writer_unlock (&error_domain_global);
103
0
}
104
105
/**
106
 * g_error_domain_register_static:
107
 * @error_type_name: static string to create a #GQuark from
108
 * @error_type_private_size: size of the private error data in bytes
109
 * @error_type_init: (scope forever): function initializing fields of the private error data
110
 * @error_type_copy: (scope forever): function copying fields of the private error data
111
 * @error_type_clear: (scope forever): function freeing fields of the private error data
112
 *
113
 * This function registers an extended #GError domain.
114
 *
115
 * @error_type_name should not be freed. @error_type_private_size must
116
 * be greater than 0.
117
 *
118
 * @error_type_init receives an initialized #GError and should then initialize
119
 * the private data.
120
 *
121
 * @error_type_copy is a function that receives both original and a copy
122
 * #GError and should copy the fields of the private error data. The standard
123
 * #GError fields are already handled.
124
 *
125
 * @error_type_clear receives the pointer to the error, and it should free the
126
 * fields of the private error data. It should not free the struct itself though.
127
 *
128
 * Normally, it is better to use G_DEFINE_EXTENDED_ERROR(), as it
129
 * already takes care of passing valid information to this function.
130
 *
131
 * Returns: #GQuark representing the error domain
132
 * Since: 2.68
133
 */
134
GQuark
135
g_error_domain_register_static (const char        *error_type_name,
136
                                gsize              error_type_private_size,
137
                                GErrorInitFunc     error_type_init,
138
                                GErrorCopyFunc     error_type_copy,
139
                                GErrorClearFunc    error_type_clear)
140
0
{
141
0
  GQuark error_quark;
142
143
0
  g_return_val_if_fail (error_type_name != NULL, 0);
144
0
  g_return_val_if_fail (error_type_private_size > 0, 0);
145
0
  g_return_val_if_fail (error_type_init != NULL, 0);
146
0
  g_return_val_if_fail (error_type_copy != NULL, 0);
147
0
  g_return_val_if_fail (error_type_clear != NULL, 0);
148
149
0
  error_quark = g_quark_from_static_string (error_type_name);
150
0
  error_domain_register (error_quark,
151
0
                         error_type_private_size,
152
0
                         error_type_init,
153
0
                         error_type_copy,
154
0
                         error_type_clear);
155
0
  return error_quark;
156
0
}
157
158
/**
159
 * g_error_domain_register:
160
 * @error_type_name: string to create a #GQuark from
161
 * @error_type_private_size: size of the private error data in bytes
162
 * @error_type_init: (scope forever): function initializing fields of the private error data
163
 * @error_type_copy: (scope forever): function copying fields of the private error data
164
 * @error_type_clear: (scope forever): function freeing fields of the private error data
165
 *
166
 * This function registers an extended #GError domain.
167
 * @error_type_name will be duplicated. Otherwise does the same as
168
 * g_error_domain_register_static().
169
 *
170
 * Returns: #GQuark representing the error domain
171
 * Since: 2.68
172
 */
173
GQuark
174
g_error_domain_register (const char        *error_type_name,
175
                         gsize              error_type_private_size,
176
                         GErrorInitFunc     error_type_init,
177
                         GErrorCopyFunc     error_type_copy,
178
                         GErrorClearFunc    error_type_clear)
179
0
{
180
0
  GQuark error_quark;
181
182
0
  g_return_val_if_fail (error_type_name != NULL, 0);
183
0
  g_return_val_if_fail (error_type_private_size > 0, 0);
184
0
  g_return_val_if_fail (error_type_init != NULL, 0);
185
0
  g_return_val_if_fail (error_type_copy != NULL, 0);
186
0
  g_return_val_if_fail (error_type_clear != NULL, 0);
187
188
0
  error_quark = g_quark_from_string (error_type_name);
189
0
  error_domain_register (error_quark,
190
0
                         error_type_private_size,
191
0
                         error_type_init,
192
0
                         error_type_copy,
193
0
                         error_type_clear);
194
0
  return error_quark;
195
0
}
196
197
static GError *
198
g_error_allocate (GQuark domain, ErrorDomainInfo *out_info)
199
12.9k
{
200
12.9k
  guint8 *allocated;
201
12.9k
  GError *error;
202
12.9k
  ErrorDomainInfo *info;
203
12.9k
  gsize private_size;
204
205
12.9k
  g_rw_lock_reader_lock (&error_domain_global);
206
12.9k
  info = error_domain_lookup (domain);
207
12.9k
  if (info != NULL)
208
0
    {
209
0
      if (out_info != NULL)
210
0
        *out_info = *info;
211
0
      private_size = info->private_size;
212
0
      g_rw_lock_reader_unlock (&error_domain_global);
213
0
    }
214
12.9k
  else
215
12.9k
    {
216
12.9k
      g_rw_lock_reader_unlock (&error_domain_global);
217
12.9k
      if (out_info != NULL)
218
12.9k
        memset (out_info, 0, sizeof (*out_info));
219
12.9k
      private_size = 0;
220
12.9k
    }
221
  /* See comments in g_type_create_instance in gtype.c to see what
222
   * this magic is about.
223
   */
224
12.9k
#ifdef ENABLE_VALGRIND
225
12.9k
  if (private_size > 0 && RUNNING_ON_VALGRIND)
226
0
    {
227
0
      private_size += ALIGN_STRUCT (1);
228
0
      allocated = g_slice_alloc0 (private_size + sizeof (GError) + sizeof (gpointer));
229
0
      *(gpointer *) (allocated + private_size + sizeof (GError)) = allocated + ALIGN_STRUCT (1);
230
0
      VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, sizeof (GError) + sizeof (gpointer), 0, TRUE);
231
0
      VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE);
232
0
    }
233
12.9k
  else
234
12.9k
#endif
235
12.9k
    allocated = g_slice_alloc0 (private_size + sizeof (GError));
236
237
12.9k
  error = (GError *) (allocated + private_size);
238
12.9k
  return error;
239
12.9k
}
240
241
/* This function takes ownership of @message. */
242
static GError *
243
g_error_new_steal (GQuark           domain,
244
                   gint             code,
245
                   gchar           *message,
246
                   ErrorDomainInfo *out_info)
247
12.9k
{
248
12.9k
  ErrorDomainInfo info;
249
12.9k
  GError *error = g_error_allocate (domain, &info);
250
251
12.9k
  error->domain = domain;
252
12.9k
  error->code = code;
253
12.9k
  error->message = message;
254
255
12.9k
  if (info.init != NULL)
256
0
    info.init (error);
257
12.9k
  if (out_info != NULL)
258
0
    *out_info = info;
259
260
12.9k
  return error;
261
12.9k
}
262
263
/**
264
 * g_error_new_valist:
265
 * @domain: error domain
266
 * @code: error code
267
 * @format: printf()-style format for error message
268
 * @args: #va_list of parameters for the message format
269
 *
270
 * Creates a new #GError with the given @domain and @code,
271
 * and a message formatted with @format.
272
 *
273
 * Returns: a new #GError
274
 *
275
 * Since: 2.22
276
 */
277
GError*
278
g_error_new_valist (GQuark       domain,
279
                    gint         code,
280
                    const gchar *format,
281
                    va_list      args)
282
12.9k
{
283
12.9k
  g_return_val_if_fail (format != NULL, NULL);
284
285
  /* Historically, GError allowed this (although it was never meant to work),
286
   * and it has significant use in the wild, which g_return_val_if_fail
287
   * would break. It should maybe g_return_val_if_fail in GLib 4.
288
   * (GNOME#660371, GNOME#560482)
289
   */
290
12.9k
  g_warn_if_fail (domain != 0);
291
292
12.9k
  return g_error_new_steal (domain, code, g_strdup_vprintf (format, args), NULL);
293
12.9k
}
294
295
/**
296
 * g_error_new:
297
 * @domain: error domain
298
 * @code: error code
299
 * @format: printf()-style format for error message
300
 * @...: parameters for message format
301
 *
302
 * Creates a new #GError with the given @domain and @code,
303
 * and a message formatted with @format.
304
 *
305
 * Returns: a new #GError
306
 */
307
GError*
308
g_error_new (GQuark       domain,
309
             gint         code,
310
             const gchar *format,
311
             ...)
312
0
{
313
0
  GError* error;
314
0
  va_list args;
315
316
0
  g_return_val_if_fail (format != NULL, NULL);
317
0
  g_return_val_if_fail (domain != 0, NULL);
318
319
0
  va_start (args, format);
320
0
  error = g_error_new_valist (domain, code, format, args);
321
0
  va_end (args);
322
323
0
  return error;
324
0
}
325
326
/**
327
 * g_error_new_literal:
328
 * @domain: error domain
329
 * @code: error code
330
 * @message: error message
331
 *
332
 * Creates a new #GError; unlike g_error_new(), @message is
333
 * not a printf()-style format string. Use this function if
334
 * @message contains text you don't have control over,
335
 * that could include printf() escape sequences.
336
 *
337
 * Returns: a new #GError
338
 **/
339
GError*
340
g_error_new_literal (GQuark         domain,
341
                     gint           code,
342
                     const gchar   *message)
343
0
{
344
0
  g_return_val_if_fail (message != NULL, NULL);
345
0
  g_return_val_if_fail (domain != 0, NULL);
346
347
0
  return g_error_new_steal (domain, code, g_strdup (message), NULL);
348
0
}
349
350
/**
351
 * g_error_free:
352
 * @error: a #GError
353
 *
354
 * Frees a #GError and associated resources.
355
 */
356
void
357
g_error_free (GError *error)
358
12.9k
{
359
12.9k
  gsize private_size;
360
12.9k
  ErrorDomainInfo *info;
361
12.9k
  guint8 *allocated;
362
363
12.9k
  g_return_if_fail (error != NULL);
364
365
12.9k
  g_rw_lock_reader_lock (&error_domain_global);
366
12.9k
  info = error_domain_lookup (error->domain);
367
12.9k
  if (info != NULL)
368
0
    {
369
0
      GErrorClearFunc clear = info->clear;
370
371
0
      private_size = info->private_size;
372
0
      g_rw_lock_reader_unlock (&error_domain_global);
373
0
      clear (error);
374
0
    }
375
12.9k
  else
376
12.9k
    {
377
12.9k
      g_rw_lock_reader_unlock (&error_domain_global);
378
12.9k
      private_size = 0;
379
12.9k
    }
380
381
12.9k
  g_free (error->message);
382
12.9k
  allocated = ((guint8 *) error) - private_size;
383
  /* See comments in g_type_free_instance in gtype.c to see what this
384
   * magic is about.
385
   */
386
12.9k
#ifdef ENABLE_VALGRIND
387
12.9k
  if (private_size > 0 && RUNNING_ON_VALGRIND)
388
0
    {
389
0
      private_size += ALIGN_STRUCT (1);
390
0
      allocated -= ALIGN_STRUCT (1);
391
0
      *(gpointer *) (allocated + private_size + sizeof (GError)) = NULL;
392
0
      g_slice_free1 (private_size + sizeof (GError) + sizeof (gpointer), allocated);
393
0
      VALGRIND_FREELIKE_BLOCK (allocated + ALIGN_STRUCT (1), 0);
394
0
      VALGRIND_FREELIKE_BLOCK (error, 0);
395
0
    }
396
12.9k
  else
397
12.9k
#endif
398
12.9k
  g_slice_free1 (private_size + sizeof (GError), allocated);
399
12.9k
}
400
401
/**
402
 * g_error_copy:
403
 * @error: a #GError
404
 *
405
 * Makes a copy of @error.
406
 *
407
 * Returns: a new #GError
408
 */
409
GError*
410
g_error_copy (const GError *error)
411
0
{
412
0
  GError *copy;
413
0
  ErrorDomainInfo info;
414
415
0
  g_return_val_if_fail (error != NULL, NULL);
416
0
  g_return_val_if_fail (error->message != NULL, NULL);
417
418
  /* See g_error_new_valist for why this doesn’t return */
419
0
  g_warn_if_fail (error->domain != 0);
420
421
0
  copy = g_error_new_steal (error->domain,
422
0
                            error->code,
423
0
                            g_strdup (error->message),
424
0
                            &info);
425
0
  if (info.copy != NULL)
426
0
    info.copy (error, copy);
427
428
0
  return copy;
429
0
}
430
431
/**
432
 * g_error_matches:
433
 * @error: (nullable): a #GError
434
 * @domain: an error domain
435
 * @code: an error code
436
 *
437
 * Returns %TRUE if @error matches @domain and @code, %FALSE
438
 * otherwise. In particular, when @error is %NULL, %FALSE will
439
 * be returned.
440
 *
441
 * If @domain contains a `FAILED` (or otherwise generic) error code,
442
 * you should generally not check for it explicitly, but should
443
 * instead treat any not-explicitly-recognized error code as being
444
 * equivalent to the `FAILED` code. This way, if the domain is
445
 * extended in the future to provide a more specific error code for
446
 * a certain case, your code will still work.
447
 *
448
 * Returns: whether @error has @domain and @code
449
 */
450
gboolean
451
g_error_matches (const GError *error,
452
                 GQuark        domain,
453
                 gint          code)
454
0
{
455
0
  return error &&
456
0
    error->domain == domain &&
457
0
    error->code == code;
458
0
}
459
460
#define ERROR_OVERWRITTEN_WARNING "GError set over the top of a previous GError or uninitialized memory.\n" \
461
               "This indicates a bug in someone's code. You must ensure an error is NULL before it's set.\n" \
462
               "The overwriting error message was: %s"
463
464
/**
465
 * g_set_error:
466
 * @err: (out callee-allocates) (optional): a return location for a #GError
467
 * @domain: error domain
468
 * @code: error code
469
 * @format: printf()-style format
470
 * @...: args for @format
471
 *
472
 * Does nothing if @err is %NULL; if @err is non-%NULL, then *@err
473
 * must be %NULL. A new #GError is created and assigned to *@err.
474
 */
475
void
476
g_set_error (GError      **err,
477
             GQuark        domain,
478
             gint          code,
479
             const gchar  *format,
480
             ...)
481
12.9k
{
482
12.9k
  GError *new;
483
484
12.9k
  va_list args;
485
486
12.9k
  if (err == NULL)
487
0
    return;
488
489
12.9k
  va_start (args, format);
490
12.9k
  new = g_error_new_valist (domain, code, format, args);
491
12.9k
  va_end (args);
492
493
12.9k
  if (*err == NULL)
494
12.9k
    *err = new;
495
0
  else
496
0
    {
497
0
      g_warning (ERROR_OVERWRITTEN_WARNING, new->message);
498
0
      g_error_free (new);
499
0
    }
500
12.9k
}
501
502
/**
503
 * g_set_error_literal:
504
 * @err: (out callee-allocates) (optional): a return location for a #GError
505
 * @domain: error domain
506
 * @code: error code
507
 * @message: error message
508
 *
509
 * Does nothing if @err is %NULL; if @err is non-%NULL, then *@err
510
 * must be %NULL. A new #GError is created and assigned to *@err.
511
 * Unlike g_set_error(), @message is not a printf()-style format string.
512
 * Use this function if @message contains text you don't have control over,
513
 * that could include printf() escape sequences.
514
 *
515
 * Since: 2.18
516
 */
517
void
518
g_set_error_literal (GError      **err,
519
                     GQuark        domain,
520
                     gint          code,
521
                     const gchar  *message)
522
7.02k
{
523
7.02k
  if (err == NULL)
524
7.02k
    return;
525
526
0
  if (*err == NULL)
527
0
    *err = g_error_new_literal (domain, code, message);
528
0
  else
529
0
    g_warning (ERROR_OVERWRITTEN_WARNING, message);
530
0
}
531
532
/**
533
 * g_propagate_error:
534
 * @dest: (out callee-allocates) (optional) (nullable): error return location
535
 * @src: (transfer full): error to move into the return location
536
 *
537
 * If @dest is %NULL, free @src; otherwise, moves @src into *@dest.
538
 * The error variable @dest points to must be %NULL.
539
 *
540
 * @src must be non-%NULL.
541
 *
542
 * Note that @src is no longer valid after this call. If you want
543
 * to keep using the same GError*, you need to set it to %NULL
544
 * after calling this function on it.
545
 */
546
void
547
g_propagate_error (GError **dest,
548
       GError  *src)
549
0
{
550
0
  g_return_if_fail (src != NULL);
551
 
552
0
  if (dest == NULL)
553
0
    {
554
0
      g_error_free (src);
555
0
      return;
556
0
    }
557
0
  else
558
0
    {
559
0
      if (*dest != NULL)
560
0
        {
561
0
          g_warning (ERROR_OVERWRITTEN_WARNING, src->message);
562
0
          g_error_free (src);
563
0
        }
564
0
      else
565
0
        *dest = src;
566
0
    }
567
0
}
568
569
/**
570
 * g_clear_error:
571
 * @err: a #GError return location
572
 *
573
 * If @err or *@err is %NULL, does nothing. Otherwise,
574
 * calls g_error_free() on *@err and sets *@err to %NULL.
575
 */
576
void
577
g_clear_error (GError **err)
578
0
{
579
0
  if (err && *err)
580
0
    {
581
0
      g_error_free (*err);
582
0
      *err = NULL;
583
0
    }
584
0
}
585
586
G_GNUC_PRINTF(2, 0)
587
static void
588
g_error_add_prefix (gchar       **string,
589
                    const gchar  *format,
590
                    va_list       ap)
591
0
{
592
0
  gchar *oldstring;
593
0
  gchar *prefix;
594
595
0
  prefix = g_strdup_vprintf (format, ap);
596
0
  oldstring = *string;
597
0
  *string = g_strconcat (prefix, oldstring, NULL);
598
0
  g_free (oldstring);
599
0
  g_free (prefix);
600
0
}
601
602
/**
603
 * g_prefix_error:
604
 * @err: (inout) (optional) (nullable): a return location for a #GError
605
 * @format: printf()-style format string
606
 * @...: arguments to @format
607
 *
608
 * Formats a string according to @format and prefix it to an existing
609
 * error message. If @err is %NULL (ie: no error variable) then do
610
 * nothing.
611
 *
612
 * If *@err is %NULL (ie: an error variable is present but there is no
613
 * error condition) then also do nothing.
614
 *
615
 * Since: 2.16
616
 */
617
void
618
g_prefix_error (GError      **err,
619
                const gchar  *format,
620
                ...)
621
0
{
622
0
  if (err && *err)
623
0
    {
624
0
      va_list ap;
625
626
0
      va_start (ap, format);
627
0
      g_error_add_prefix (&(*err)->message, format, ap);
628
0
      va_end (ap);
629
0
    }
630
0
}
631
632
/**
633
 * g_prefix_error_literal:
634
 * @err: (inout) (nullable) (optional): a return location for a #GError, or %NULL
635
 * @prefix: string to prefix @err with
636
 *
637
 * Prefixes @prefix to an existing error message. If @err or *@err is
638
 * %NULL (i.e.: no error variable) then do nothing.
639
 *
640
 * Since: 2.70
641
 */
642
void
643
g_prefix_error_literal (GError      **err,
644
                        const gchar  *prefix)
645
0
{
646
0
  if (err && *err)
647
0
    {
648
0
      gchar *oldstring;
649
650
0
      oldstring = (*err)->message;
651
0
      (*err)->message = g_strconcat (prefix, oldstring, NULL);
652
0
      g_free (oldstring);
653
0
    }
654
0
}
655
656
/**
657
 * g_propagate_prefixed_error:
658
 * @dest: error return location
659
 * @src: error to move into the return location
660
 * @format: printf()-style format string
661
 * @...: arguments to @format
662
 *
663
 * If @dest is %NULL, free @src; otherwise, moves @src into *@dest.
664
 * *@dest must be %NULL. After the move, add a prefix as with
665
 * g_prefix_error().
666
 *
667
 * Since: 2.16
668
 **/
669
void
670
g_propagate_prefixed_error (GError      **dest,
671
                            GError       *src,
672
                            const gchar  *format,
673
                            ...)
674
0
{
675
0
  g_propagate_error (dest, src);
676
677
0
  if (dest)
678
0
    {
679
0
      va_list ap;
680
681
0
      g_assert (*dest != NULL);
682
0
      va_start (ap, format);
683
0
      g_error_add_prefix (&(*dest)->message, format, ap);
684
      va_end (ap);
685
0
    }
686
0
}