Coverage Report

Created: 2026-09-06 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/httpd/srclib/apr/misc/unix/errorcodes.c
Line
Count
Source
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
 * contributor license agreements.  See the NOTICE file distributed with
3
 * this work for additional information regarding copyright ownership.
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * (the "License"); you may not use this file except in compliance with
6
 * the License.  You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include "apr_arch_misc.h"
18
#include "apr_strings.h"
19
#include "apr_lib.h"
20
#include "apr_dso.h"
21
22
#include "apu_errno.h"
23
24
#if APR_HAVE_NETDB_H
25
#include <netdb.h>
26
#endif
27
#ifdef HAVE_DLFCN_H
28
#include <dlfcn.h>
29
#endif
30
31
/*
32
 * stuffbuffer - like apr_cpystrn() but returns the address of the
33
 * dest buffer instead of the address of the terminating '\0'
34
 */
35
static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s)
36
0
{
37
0
    apr_cpystrn(buf,s,bufsize);
38
0
    return buf;
39
0
}
40
41
static char *apr_error_string(apr_status_t statcode)
42
0
{
43
0
    switch (statcode) {
44
0
    case APR_ENOSTAT:
45
0
        return "Could not perform a stat on the file.";
46
0
    case APR_ENOPOOL:
47
0
        return "A new pool could not be created.";
48
0
    case APR_EBADDATE:
49
0
        return "An invalid date has been provided";
50
0
    case APR_EINVALSOCK:
51
0
        return "An invalid socket was returned";
52
0
    case APR_ENOPROC:
53
0
        return "No process was provided and one was required.";
54
0
    case APR_ENOTIME:
55
0
        return "No time was provided and one was required.";
56
0
    case APR_ENODIR:
57
0
        return "No directory was provided and one was required.";
58
0
    case APR_ENOLOCK:
59
0
        return "No lock was provided and one was required.";
60
0
    case APR_ENOPOLL:
61
0
        return "No poll structure was provided and one was required.";
62
0
    case APR_ENOSOCKET:
63
0
        return "No socket was provided and one was required.";
64
0
    case APR_ENOTHREAD:
65
0
        return "No thread was provided and one was required.";
66
0
    case APR_ENOTHDKEY:
67
0
        return "No thread key structure was provided and one was required.";
68
0
    case APR_ENOSHMAVAIL:
69
0
        return "No shared memory is currently available";
70
0
    case APR_EDSOOPEN:
71
#if APR_HAS_DSO && defined(HAVE_LIBDL)
72
        return dlerror();
73
#else
74
0
        return "DSO load failed";
75
0
#endif /* HAVE_LIBDL */
76
0
    case APR_EBADIP:
77
0
        return "The specified IP address is invalid.";
78
0
    case APR_EBADMASK:
79
0
        return "The specified network mask is invalid.";
80
0
    case APR_ESYMNOTFOUND:
81
0
        return "Could not find the requested symbol.";
82
0
    case APR_ENOTENOUGHENTROPY:
83
0
        return "Not enough entropy to continue.";
84
0
    case APR_INCHILD:
85
0
        return
86
0
      "Your code just forked, and you are currently executing in the "
87
0
      "child process";
88
0
    case APR_INPARENT:
89
0
        return
90
0
      "Your code just forked, and you are currently executing in the "
91
0
      "parent process";
92
0
    case APR_DETACH:
93
0
        return "The specified thread is detached";
94
0
    case APR_NOTDETACH:
95
0
        return "The specified thread is not detached";
96
0
    case APR_CHILD_DONE:
97
0
        return "The specified child process is done executing";
98
0
    case APR_CHILD_NOTDONE:
99
0
        return "The specified child process is not done executing";
100
0
    case APR_TIMEUP:
101
0
        return "The timeout specified has expired";
102
0
    case APR_INCOMPLETE:
103
0
        return "Partial results are valid but processing is incomplete";
104
0
    case APR_BADCH:
105
0
        return "Bad character specified on command line";
106
0
    case APR_BADARG:
107
0
        return "Missing parameter for the specified command line option";
108
0
    case APR_EOF:
109
0
        return "End of file found";
110
0
    case APR_NOTFOUND:
111
0
        return "Could not find specified socket in poll list.";
112
0
    case APR_ANONYMOUS:
113
0
        return "Shared memory is implemented anonymously";
114
0
    case APR_FILEBASED:
115
0
        return "Shared memory is implemented using files";
116
0
    case APR_KEYBASED:
117
0
        return "Shared memory is implemented using a key system";
118
0
    case APR_EINIT:
119
0
        return
120
0
      "There is no error, this value signifies an initialized "
121
0
      "error code";
122
0
    case APR_ENOTIMPL:
123
0
        return "This function has not been implemented on this platform";
124
0
    case APR_EMISMATCH:
125
0
        return "passwords do not match";
126
0
    case APR_EABSOLUTE:
127
0
        return "The given path is absolute";
128
0
    case APR_ERELATIVE:
129
0
        return "The given path is relative";
130
0
    case APR_EINCOMPLETE:
131
0
        return "The given path is incomplete";
132
0
    case APR_EABOVEROOT:
133
0
        return "The given path was above the root path";
134
0
    case APR_EBADPATH:
135
0
        return "The given path is misformatted or contained invalid characters";
136
0
    case APR_EPATHWILD:
137
0
        return "The given path contained wildcard characters";
138
0
    case APR_EBUSY:
139
0
        return "The given lock was busy.";
140
0
    case APR_EPROC_UNKNOWN:
141
0
        return "The process is not recognized.";
142
0
    case APR_EALREADY:
143
0
        return "Operation already in progress";
144
0
    case APR_EGENERAL:
145
0
        return "Internal error (specific information not available)";
146
147
/* APR Util error codes */
148
149
0
    case APR_ENOKEY:
150
0
        return "The key provided was empty or NULL";
151
0
    case APR_ENOIV:
152
0
        return "The initialisation vector provided was NULL";
153
0
    case APR_EKEYTYPE:
154
0
        return "The key type was not recognised";
155
0
    case APR_ENOSPACE:
156
0
        return "The buffer supplied was not big enough";
157
0
    case APR_ECRYPT:
158
0
        return "Internal error in the crypto subsystem (specific information not available)";
159
0
    case APR_EPADDING:
160
0
        return "Padding was not supported";
161
0
    case APR_EKEYLENGTH:
162
0
        return "The key length was incorrect";
163
0
    case APR_ENOCIPHER:
164
0
        return "The cipher provided was not recognised";
165
0
    case APR_ENODIGEST:
166
0
        return "The digest provided was not recognised";
167
0
    case APR_ENOENGINE:
168
0
        return "No engine found for crypto subsystem";
169
0
    case APR_EINITENGINE:
170
0
        return "Failed to init engine for crypto subsystem";
171
0
    case APR_EREINIT:
172
0
        return "Underlying crypto has already been initialised";
173
0
    case APR_ENOVERIFY:
174
0
        return "The signature verification failed";
175
176
0
    case APR_WANT_READ:
177
0
        return "Call me again when the socket is ready for reading";
178
0
    case APR_WANT_WRITE:
179
0
        return "Call me again when the socket is ready for writing";
180
181
0
    case APR_OTHER:
182
0
      return "An internal LDAP error has occurred";
183
0
    case APR_SERVER_DOWN:
184
0
        return "The server is down";
185
0
    case APR_LOCAL_ERROR:
186
0
        return "An error has occurred locally";
187
0
    case APR_ENCODING_ERROR:
188
0
        return "Encoding has failed";
189
0
    case APR_DECODING_ERROR:
190
0
        return "Decoding has failed";
191
0
    case APR_AUTH_UNKNOWN:
192
0
        return "Unknown SASL mechanism";
193
0
    case APR_FILTER_ERROR:
194
0
        return "The filter was malformed";
195
0
    case APR_USER_CANCELLED:
196
0
        return "User has cancelled the request";
197
0
    case APR_PARAM_ERROR:
198
0
      return "Parameter error";
199
0
    case APR_CONNECT_ERROR:
200
0
      return "Connect error";
201
0
    case APR_NOT_SUPPORTED:
202
0
      return "Not supported";
203
0
    case APR_CONTROL_NOT_FOUND:
204
0
      return "Control not found";
205
0
    case APR_NO_RESULTS_RETURNED:
206
0
      return "No results returned";
207
0
    case APR_MORE_RESULTS_TO_RETURN:
208
0
      return "More results to be returned";
209
0
    case APR_CLIENT_LOOP:
210
0
      return "Client loop has occurred";
211
0
    case APR_REFERRAL_LIMIT_EXCEEDED:
212
0
      return "Referral limit exceeded";
213
0
    case APR_CONNECTING:
214
0
      return "Connecting";
215
216
0
    case APR_OPERATIONS_ERROR:
217
0
      return "Operations error has occurred";
218
0
    case APR_PROTOCOL_ERROR:
219
0
      return "Protocol error has occurred";
220
0
    case APR_TIMELIMIT_EXCEEDED:
221
0
      return "Time limit has been exceeded";
222
0
    case APR_SIZELIMIT_EXCEEDED:
223
0
      return "Size limit has been exceeded";
224
0
    case APR_PROXY_AUTH:
225
0
        return "Proxy authorization has failed";
226
0
    case APR_INAPPROPRIATE_AUTH:
227
0
        return "Authentication not appropriate for this entry";
228
0
    case APR_INVALID_CREDENTIALS:
229
0
        return "Invalid credentials were presented";
230
0
    case APR_INSUFFICIENT_ACCESS:
231
0
        return "The user has insufficient access";
232
0
    case APR_UNAVAILABLE:
233
0
        return "Unavailable";
234
0
    case APR_CONSTRAINT_VIOLATION:
235
0
        return "A constraint was violated";
236
0
    case APR_NO_SUCH_OBJECT:
237
0
        return "No such object";
238
0
    case APR_NO_SUCH_ATTRIBUTE:
239
0
        return "No such attribute";
240
0
    case APR_COMPARE_TRUE:
241
0
        return "Comparison is true";
242
0
    case APR_COMPARE_FALSE:
243
0
        return "Comparison is false";
244
0
    case APR_ALREADY_EXISTS:
245
0
        return "The object already exists";
246
0
    case APR_OBJECT_CLASS_VIOLATION:
247
0
        return "Add or modify results in an objectclass violation";
248
249
0
    default:
250
0
        return "Error string not specified yet";
251
0
    }
252
0
}
253
254
255
#ifdef OS2
256
#include <ctype.h>
257
258
int apr_canonical_error(apr_status_t err);
259
260
static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
261
{
262
  char result[200];
263
  unsigned char message[HUGE_STRING_LEN];
264
  ULONG len;
265
  char *pos;
266
  int c;
267
268
  if (err >= 10000 && err < 12000) {  /* socket error codes */
269
      return stuffbuffer(buf, bufsize,
270
                         strerror(apr_canonical_error(err+APR_OS_START_SYSERR)));
271
  }
272
  else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err,
273
       "OSO001.MSG", &len) == 0) {
274
      len--;
275
      message[len] = 0;
276
      pos = result;
277
278
      if (len >= sizeof(result))
279
        len = sizeof(result) - 1;
280
281
      for (c=0; c<len; c++) {
282
    /* skip multiple whitespace */
283
          while (apr_isspace(message[c]) && apr_isspace(message[c+1]))
284
              c++;
285
          *(pos++) = apr_isspace(message[c]) ? ' ' : message[c];
286
      }
287
288
      *pos = 0;
289
  }
290
  else {
291
      sprintf(result, "OS/2 error %d", err);
292
  }
293
294
  /* Stuff the string into the caller supplied buffer, then return
295
   * a pointer to it.
296
   */
297
  return stuffbuffer(buf, bufsize, result);
298
}
299
300
#elif defined(WIN32)
301
302
static const struct {
303
    apr_status_t code;
304
    const char *msg;
305
} gaErrorList[] = {
306
    {WSAEINTR,           "Interrupted system call"},
307
    {WSAEBADF,           "Bad file number"},
308
    {WSAEACCES,          "Permission denied"},
309
    {WSAEFAULT,          "Bad address"},
310
    {WSAEINVAL,          "Invalid argument"},
311
    {WSAEMFILE,          "Too many open sockets"},
312
    {WSAEWOULDBLOCK,     "Operation would block"},
313
    {WSAEINPROGRESS,     "Operation now in progress"},
314
    {WSAEALREADY,        "Operation already in progress"},
315
    {WSAENOTSOCK,        "Socket operation on non-socket"},
316
    {WSAEDESTADDRREQ,    "Destination address required"},
317
    {WSAEMSGSIZE,        "Message too long"},
318
    {WSAEPROTOTYPE,      "Protocol wrong type for socket"},
319
    {WSAENOPROTOOPT,     "Bad protocol option"},
320
    {WSAEPROTONOSUPPORT, "Protocol not supported"},
321
    {WSAESOCKTNOSUPPORT, "Socket type not supported"},
322
    {WSAEOPNOTSUPP,      "Operation not supported on socket"},
323
    {WSAEPFNOSUPPORT,    "Protocol family not supported"},
324
    {WSAEAFNOSUPPORT,    "Address family not supported"},
325
    {WSAEADDRINUSE,      "Address already in use"},
326
    {WSAEADDRNOTAVAIL,   "Can't assign requested address"},
327
    {WSAENETDOWN,        "Network is down"},
328
    {WSAENETUNREACH,     "Network is unreachable"},
329
    {WSAENETRESET,       "Net connection reset"},
330
    {WSAECONNABORTED,    "Software caused connection abort"},
331
    {WSAECONNRESET,      "Connection reset by peer"},
332
    {WSAENOBUFS,         "No buffer space available"},
333
    {WSAEISCONN,         "Socket is already connected"},
334
    {WSAENOTCONN,        "Socket is not connected"},
335
    {WSAESHUTDOWN,       "Can't send after socket shutdown"},
336
    {WSAETOOMANYREFS,    "Too many references, can't splice"},
337
    {WSAETIMEDOUT,       "Connection timed out"},
338
    {WSAECONNREFUSED,    "Connection refused"},
339
    {WSAELOOP,           "Too many levels of symbolic links"},
340
    {WSAENAMETOOLONG,    "File name too long"},
341
    {WSAEHOSTDOWN,       "Host is down"},
342
    {WSAEHOSTUNREACH,    "No route to host"},
343
    {WSAENOTEMPTY,       "Directory not empty"},
344
    {WSAEPROCLIM,        "Too many processes"},
345
    {WSAEUSERS,          "Too many users"},
346
    {WSAEDQUOT,          "Disc quota exceeded"},
347
    {WSAESTALE,          "Stale NFS file handle"},
348
    {WSAEREMOTE,         "Too many levels of remote in path"},
349
    {WSASYSNOTREADY,     "Network system is unavailable"},
350
    {WSAVERNOTSUPPORTED, "Winsock version out of range"},
351
    {WSANOTINITIALISED,  "WSAStartup not yet called"},
352
    {WSAEDISCON,         "Graceful shutdown in progress"},
353
    {WSAHOST_NOT_FOUND,  "Host not found"},
354
    {WSANO_DATA,         "No host data of that type was found"},
355
    {0,                  NULL}
356
};
357
358
359
static char *apr_os_strerror(char *buf, apr_size_t bufsize, apr_status_t errcode)
360
{
361
    apr_size_t len=0, i;
362
363
    len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
364
                      | FORMAT_MESSAGE_IGNORE_INSERTS,
365
                        NULL,
366
                        errcode,
367
                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
368
                        buf,
369
                        (DWORD)bufsize,
370
                        NULL);
371
372
    if (!len) {
373
        for (i = 0; gaErrorList[i].msg; ++i) {
374
            if (gaErrorList[i].code == errcode) {
375
                apr_cpystrn(buf, gaErrorList[i].msg, bufsize);
376
                len = strlen(buf);
377
                break;
378
            }
379
        }
380
    }
381
382
    if (len) {
383
        /* FormatMessage put the message in the buffer, but it may
384
         * have embedded a newline (\r\n), and possible more than one.
385
         * Remove the newlines replacing them with a space. This is not
386
         * as visually perfect as moving all the remaining message over,
387
         * but more efficient.
388
         */
389
        i = len;
390
        while (i) {
391
            i--;
392
            if ((buf[i] == '\r') || (buf[i] == '\n'))
393
                buf[i] = ' ';
394
        }
395
    }
396
    else {
397
        /* Windows didn't provide us with a message.  Even stuff like                    * WSAECONNREFUSED won't get a message.
398
         */
399
        apr_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode);
400
    }
401
402
    return buf;
403
}
404
405
#else
406
/* On Unix, apr_os_strerror() handles error codes from the resolver
407
 * (h_errno).
408
 */
409
static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
410
0
{
411
#ifdef HAVE_HSTRERROR
412
    return stuffbuffer(buf, bufsize, hstrerror(err));
413
#else /* HAVE_HSTRERROR */
414
0
    const char *msg;
415
416
0
    switch(err) {
417
0
    case HOST_NOT_FOUND:
418
0
        msg = "Unknown host";
419
0
        break;
420
0
#if defined(NO_DATA)
421
0
    case NO_DATA:
422
#if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS)
423
    case NO_ADDRESS:
424
#endif
425
0
        msg = "No address for host";
426
0
        break;
427
#elif defined(NO_ADDRESS)
428
    case NO_ADDRESS:
429
        msg = "No address for host";
430
        break;
431
#endif /* NO_DATA */
432
0
    default:
433
0
        msg = "Unrecognized resolver error";
434
0
    }
435
0
    return stuffbuffer(buf, bufsize, msg);
436
0
#endif /* HAVE_STRERROR */
437
0
}
438
#endif
439
440
#if defined(HAVE_STRERROR_R) && defined(STRERROR_R_RC_INT)
441
/* AIX and Tru64 style */
442
static char *native_strerror(apr_status_t statcode, char *buf,
443
                             apr_size_t bufsize)
444
{
445
    if (strerror_r(statcode, buf, bufsize) < 0) {
446
        return stuffbuffer(buf, bufsize,
447
                           "APR does not understand this error code");
448
    }
449
    else {
450
        return buf;
451
    }
452
}
453
#elif defined(HAVE_STRERROR_R)
454
/* glibc style */
455
456
static char *native_strerror(apr_status_t statcode, char *buf,
457
                             apr_size_t bufsize)
458
0
{
459
0
    const char *msg;
460
461
0
    buf[0] = '\0';
462
0
    msg = strerror_r(statcode, buf, bufsize);
463
0
    if (buf[0] == '\0') { /* libc didn't use our buffer */
464
0
        return stuffbuffer(buf, bufsize, msg);
465
0
    }
466
0
    else {
467
0
        return buf;
468
0
    }
469
0
}
470
#else
471
/* plain old strerror();
472
 * thread-safe on some platforms (e.g., Solaris, OS/390)
473
 */
474
static char *native_strerror(apr_status_t statcode, char *buf,
475
                             apr_size_t bufsize)
476
{
477
    const char *err = strerror(statcode);
478
    if (err) {
479
        return stuffbuffer(buf, bufsize, err);
480
    } else {
481
        return stuffbuffer(buf, bufsize,
482
                           "APR does not understand this error code");
483
    }
484
}
485
#endif
486
487
APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
488
                                 apr_size_t bufsize)
489
0
{
490
0
    if (statcode < APR_OS_START_ERROR) {
491
0
        return native_strerror(statcode, buf, bufsize);
492
0
    }
493
0
    else if (statcode < APR_OS_START_USERERR) {
494
0
        return stuffbuffer(buf, bufsize, apr_error_string(statcode));
495
0
    }
496
0
    else if (statcode < APR_OS_START_EAIERR) {
497
0
        return stuffbuffer(buf, bufsize, "APR does not understand this error code");
498
0
    }
499
0
    else if (statcode < APR_OS_START_SYSERR) {
500
0
#if defined(HAVE_GAI_STRERROR)
501
0
        statcode -= APR_OS_START_EAIERR;
502
0
#if defined(NEGATIVE_EAI)
503
0
        statcode = -statcode;
504
0
#endif
505
0
        return stuffbuffer(buf, bufsize, gai_strerror(statcode));
506
#else
507
        return stuffbuffer(buf, bufsize, "APR does not understand this error code");
508
#endif
509
0
    }
510
0
    else {
511
0
        return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);
512
0
    }
513
0
}
514