Coverage Report

Created: 2025-07-11 06:40

/src/httpd/srclib/apr/misc/unix/errorcodes.c
Line
Count
Source (jump to first uncovered line)
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) || (defined(NETWARE) && defined(USE_WINSOCK))
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
#ifndef NETWARE
364
    len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
365
                      | FORMAT_MESSAGE_IGNORE_INSERTS,
366
                        NULL,
367
                        errcode,
368
                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
369
                        buf,
370
                        (DWORD)bufsize,
371
                        NULL);
372
#endif
373
374
    if (!len) {
375
        for (i = 0; gaErrorList[i].msg; ++i) {
376
            if (gaErrorList[i].code == errcode) {
377
                apr_cpystrn(buf, gaErrorList[i].msg, bufsize);
378
                len = strlen(buf);
379
                break;
380
            }
381
        }
382
    }
383
384
    if (len) {
385
        /* FormatMessage put the message in the buffer, but it may
386
         * have embedded a newline (\r\n), and possible more than one.
387
         * Remove the newlines replacing them with a space. This is not
388
         * as visually perfect as moving all the remaining message over,
389
         * but more efficient.
390
         */
391
        i = len;
392
        while (i) {
393
            i--;
394
            if ((buf[i] == '\r') || (buf[i] == '\n'))
395
                buf[i] = ' ';
396
        }
397
    }
398
    else {
399
        /* Windows didn't provide us with a message.  Even stuff like                    * WSAECONNREFUSED won't get a message.
400
         */
401
        apr_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode);
402
    }
403
404
    return buf;
405
}
406
407
#else
408
/* On Unix, apr_os_strerror() handles error codes from the resolver
409
 * (h_errno).
410
 */
411
static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
412
0
{
413
#ifdef HAVE_HSTRERROR
414
    return stuffbuffer(buf, bufsize, hstrerror(err));
415
#else /* HAVE_HSTRERROR */
416
0
    const char *msg;
417
418
0
    switch(err) {
419
0
    case HOST_NOT_FOUND:
420
0
        msg = "Unknown host";
421
0
        break;
422
0
#if defined(NO_DATA)
423
0
    case NO_DATA:
424
#if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS)
425
    case NO_ADDRESS:
426
#endif
427
0
        msg = "No address for host";
428
0
        break;
429
#elif defined(NO_ADDRESS)
430
    case NO_ADDRESS:
431
        msg = "No address for host";
432
        break;
433
#endif /* NO_DATA */
434
0
    default:
435
0
        msg = "Unrecognized resolver error";
436
0
    }
437
0
    return stuffbuffer(buf, bufsize, msg);
438
0
#endif /* HAVE_STRERROR */
439
0
}
440
#endif
441
442
#if defined(HAVE_STRERROR_R) && defined(STRERROR_R_RC_INT) && !defined(BEOS)
443
/* AIX and Tru64 style */
444
static char *native_strerror(apr_status_t statcode, char *buf,
445
                             apr_size_t bufsize)
446
{
447
    if (strerror_r(statcode, buf, bufsize) < 0) {
448
        return stuffbuffer(buf, bufsize,
449
                           "APR does not understand this error code");
450
    }
451
    else {
452
        return buf;
453
    }
454
}
455
#elif defined(HAVE_STRERROR_R)
456
/* glibc style */
457
458
/* BeOS has the function available, but it doesn't provide
459
 * the prototype publicly (doh!), so to avoid a build warning
460
 * we add a suitable prototype here.
461
 */
462
#if defined(BEOS)
463
const char *strerror_r(apr_status_t, char *, apr_size_t);
464
#endif
465
466
static char *native_strerror(apr_status_t statcode, char *buf,
467
                             apr_size_t bufsize)
468
0
{
469
0
    const char *msg;
470
471
0
    buf[0] = '\0';
472
0
    msg = strerror_r(statcode, buf, bufsize);
473
0
    if (buf[0] == '\0') { /* libc didn't use our buffer */
474
0
        return stuffbuffer(buf, bufsize, msg);
475
0
    }
476
0
    else {
477
0
        return buf;
478
0
    }
479
0
}
480
#else
481
/* plain old strerror();
482
 * thread-safe on some platforms (e.g., Solaris, OS/390)
483
 */
484
static char *native_strerror(apr_status_t statcode, char *buf,
485
                             apr_size_t bufsize)
486
{
487
    const char *err = strerror(statcode);
488
    if (err) {
489
        return stuffbuffer(buf, bufsize, err);
490
    } else {
491
        return stuffbuffer(buf, bufsize,
492
                           "APR does not understand this error code");
493
    }
494
}
495
#endif
496
497
APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
498
                                 apr_size_t bufsize)
499
0
{
500
0
    if (statcode < APR_OS_START_ERROR) {
501
0
        return native_strerror(statcode, buf, bufsize);
502
0
    }
503
0
    else if (statcode < APR_OS_START_USERERR) {
504
0
        return stuffbuffer(buf, bufsize, apr_error_string(statcode));
505
0
    }
506
0
    else if (statcode < APR_OS_START_EAIERR) {
507
0
        return stuffbuffer(buf, bufsize, "APR does not understand this error code");
508
0
    }
509
0
    else if (statcode < APR_OS_START_SYSERR) {
510
0
#if defined(HAVE_GAI_STRERROR)
511
0
        statcode -= APR_OS_START_EAIERR;
512
0
#if defined(NEGATIVE_EAI)
513
0
        statcode = -statcode;
514
0
#endif
515
0
        return stuffbuffer(buf, bufsize, gai_strerror(statcode));
516
#else
517
        return stuffbuffer(buf, bufsize, "APR does not understand this error code");
518
#endif
519
0
    }
520
0
    else {
521
0
        return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);
522
0
    }
523
0
}
524