Coverage Report

Created: 2024-02-29 06:05

/src/strongswan/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2009-2013 Tobias Brunner
3
 * Copyright (C) 2006-2008 Martin Willi
4
 *
5
 * Copyright (C) secunet Security Networks AG
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
#include "printf_hook.h"
19
20
#include <utils/utils.h>
21
#include <utils/debug.h>
22
23
#include <stdio.h>
24
#include <stdarg.h>
25
#include <string.h>
26
#include <printf.h>
27
28
typedef struct private_printf_hook_t private_printf_hook_t;
29
typedef struct printf_hook_handler_t printf_hook_handler_t;
30
31
/**
32
 * private data of printf_hook
33
 */
34
struct private_printf_hook_t {
35
36
  /**
37
   * public functions
38
   */
39
  printf_hook_t public;
40
};
41
42
/**
43
 * struct with information about a registered handler
44
 */
45
struct printf_hook_handler_t {
46
47
  /**
48
   * callback function
49
   */
50
  printf_hook_function_t hook;
51
52
  /**
53
   * number of arguments
54
   */
55
  int numargs;
56
57
  /**
58
   * types of the arguments, PA_*
59
   */
60
  int argtypes[3];
61
};
62
63
/**
64
 * Data to pass to a printf hook.
65
 */
66
struct printf_hook_data_t {
67
68
  /**
69
   * Output FILE stream
70
   */
71
  FILE *stream;;
72
};
73
74
/* A-Z | 6 other chars | a-z */
75
static printf_hook_handler_t *printf_hooks[58];
76
77
105k
#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
78
79
/**
80
 * Glibc variant of print_in_hook()
81
 */
82
size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...)
83
0
{
84
0
  ssize_t written;
85
0
  va_list args;
86
87
0
  va_start(args, fmt);
88
0
  written = vfprintf(data->stream, fmt, args);
89
0
  va_end(args);
90
91
0
  if (written < 0)
92
0
  {
93
0
    written = 0;
94
0
  }
95
0
  return written;
96
0
}
97
98
/**
99
 * Printf hook print function. This is actually of type "printf_function",
100
 * however glibc does it typedef to function, but uclibc to a pointer.
101
 * So we redefine it here.
102
 */
103
static int custom_print(FILE *stream, const struct printf_info *info,
104
            const void *const *args)
105
0
{
106
0
  printf_hook_spec_t spec;
107
0
  printf_hook_handler_t *handler;
108
0
  printf_hook_data_t data = {
109
0
    .stream = stream,
110
0
  };
111
112
0
  handler =  printf_hooks[SPEC_TO_INDEX(info->spec)];
113
0
  spec.hash = info->alt;
114
0
  spec.plus = info->showsign;
115
0
  spec.minus = info->left;
116
0
  spec.width = info->width;
117
118
0
  return handler->hook(&data, &spec, args);
119
0
}
120
121
/**
122
 * Printf hook arginfo function, which is actually of type
123
 * "printf_arginfo_[size_]function".
124
 */
125
static int custom_arginfo(const struct printf_info *info, size_t n, int *argtypes
126
#ifdef HAVE_PRINTF_SPECIFIER
127
              , int *size
128
#endif
129
              )
130
0
{
131
0
  int i;
132
0
  printf_hook_handler_t *handler;
133
134
0
  handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
135
0
  if (handler->numargs <= n)
136
0
  {
137
0
    for (i = 0; i < handler->numargs; ++i)
138
0
    {
139
0
      argtypes[i] = handler->argtypes[i];
140
0
    }
141
0
  }
142
  /* we never set "size", as we have no user defined types */
143
0
  return handler->numargs;
144
0
}
145
146
METHOD(printf_hook_t, add_handler, void,
147
  private_printf_hook_t *this, char spec,
148
            printf_hook_function_t hook, ...)
149
35.2k
{
150
35.2k
  int i = -1;
151
35.2k
  bool failed = FALSE;
152
35.2k
  printf_hook_handler_t *handler;
153
35.2k
  printf_hook_argtype_t argtype;
154
35.2k
  va_list args;
155
156
35.2k
  if (SPEC_TO_INDEX(spec) <= -1 ||
157
35.2k
    SPEC_TO_INDEX(spec) >= countof(printf_hooks))
158
0
  {
159
0
    DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, "
160
0
       "not registered!", spec);
161
0
    return;
162
0
  }
163
164
35.2k
  INIT(handler,
165
35.2k
    .hook = hook,
166
35.2k
  );
167
168
35.2k
  va_start(args, hook);
169
86.2k
  while (!failed)
170
86.2k
  {
171
86.2k
    argtype = va_arg(args, printf_hook_argtype_t);
172
173
86.2k
    if (argtype == PRINTF_HOOK_ARGTYPE_END)
174
35.2k
    {
175
35.2k
      break;
176
35.2k
    }
177
50.9k
    if (++i >= countof(handler->argtypes))
178
0
    {
179
0
      DBG1(DBG_LIB, "Too many arguments for printf hook with "
180
0
         "specifier '%c', not registered!", spec);
181
0
      failed = TRUE;
182
0
      break;
183
0
    }
184
50.9k
    switch (argtype)
185
50.9k
    {
186
11.7k
      case PRINTF_HOOK_ARGTYPE_INT:
187
11.7k
        handler->argtypes[i] = PA_INT;
188
11.7k
        break;
189
39.2k
      case PRINTF_HOOK_ARGTYPE_POINTER:
190
39.2k
        handler->argtypes[i] = PA_POINTER;
191
39.2k
        break;
192
0
      default:
193
0
        DBG1(DBG_LIB, "Invalid printf hook arg type for '%c'", spec);
194
0
        failed = TRUE;
195
0
        break;
196
50.9k
    }
197
50.9k
  }
198
35.2k
  va_end(args);
199
200
35.2k
  handler->numargs = i + 1;
201
35.2k
  if (!failed && handler->numargs > 0)
202
35.2k
  {
203
35.2k
# ifdef HAVE_PRINTF_SPECIFIER
204
35.2k
    register_printf_specifier(spec, custom_print, custom_arginfo);
205
# else
206
    register_printf_function(spec, custom_print, custom_arginfo);
207
# endif
208
35.2k
    printf_hooks[SPEC_TO_INDEX(spec)] = handler;
209
35.2k
  }
210
0
  else
211
0
  {
212
0
    free(handler);
213
0
  }
214
35.2k
}
215
216
METHOD(printf_hook_t, destroy, void,
217
  private_printf_hook_t *this)
218
3.92k
{
219
3.92k
  int i;
220
221
231k
  for (i = 0; i < countof(printf_hooks); i++)
222
227k
  {
223
227k
    free(printf_hooks[i]);
224
227k
  }
225
3.92k
  free(this);
226
3.92k
}
227
228
/*
229
 * see header file
230
 */
231
printf_hook_t *printf_hook_create()
232
3.92k
{
233
3.92k
  private_printf_hook_t *this;
234
235
3.92k
  INIT(this,
236
3.92k
    .public = {
237
3.92k
      .add_handler = _add_handler,
238
3.92k
      .destroy = _destroy,
239
3.92k
    },
240
3.92k
  );
241
242
3.92k
  memset(printf_hooks, 0, sizeof(printf_hooks));
243
244
3.92k
  return &this->public;
245
3.92k
}