Changeset 3e828ea in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2019-09-23T12:49:29Z (7 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9be2358
Parents:
9259d20 (diff), 1a4ec93f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jiri Svoboda <jiri@…> (2019-09-22 12:49:07)
git-committer:
Jiri Svoboda <jiri@…> (2019-09-23 12:49:29)
Message:

Merge changes from master, especially Meson build

Location:
uspace/lib/c/generic
Files:
12 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/async/server.c

    r9259d20 r3e828ea  
    114114#include <stdlib.h>
    115115#include <mem.h>
    116 #include <stdlib.h>
    117116#include <macros.h>
    118117#include <str_error.h>
  • uspace/lib/c/generic/ctype.c

    r9259d20 r3e828ea  
    9090        case '\v':
    9191                return 1;
    92                 break;
    9392        default:
    9493                return 0;
  • uspace/lib/c/generic/dirent.c

    r9259d20 r3e828ea  
    3939#include <errno.h>
    4040#include <assert.h>
     41#include <string.h>
    4142
    4243struct __dirstream {
     
    9293        ssize_t len = 0;
    9394
    94         rc = vfs_read_short(dirp->fd, dirp->pos, &dirp->res.d_name[0],
    95             NAME_MAX + 1, &len);
     95        rc = vfs_read_short(dirp->fd, dirp->pos, dirp->res.d_name,
     96            sizeof(dirp->res.d_name), &len);
    9697        if (rc != EOK) {
    9798                errno = rc;
    9899                return NULL;
    99100        }
     101
     102        assert(strnlen(dirp->res.d_name, sizeof(dirp->res.d_name)) < sizeof(dirp->res.d_name));
    100103
    101104        dirp->pos += len;
  • uspace/lib/c/generic/dlfcn.c

    r9259d20 r3e828ea  
    3535 */
    3636
     37#include <errno.h>
    3738#include <stdio.h>
    3839#include <stdlib.h>
     
    4445#include <rtld/module.h>
    4546#include <rtld/rtld.h>
     47#include <rtld/rtld_arch.h>
    4648#include <rtld/symbol.h>
    4749
     
    5355        if (m == NULL) {
    5456                m = module_load(runtime_env, path, mlf_local);
    55                 module_load_deps(m, mlf_local);
     57                if (m == NULL) {
     58                        return NULL;
     59                }
     60
     61                if (module_load_deps(m, mlf_local) != EOK) {
     62                        return NULL;
     63                }
     64
    5665                /* Now relocate. */
    5766                module_process_relocs(m);
     
    7180        sd = symbol_bfs_find(sym_name, (module_t *) mod, &sm);
    7281        if (sd != NULL) {
    73                 return symbol_get_addr(sd, sm, __tcb_get());
     82                if (elf_st_type(sd->st_info) == STT_FUNC)
     83                        return func_get_addr(sd, sm);
     84                else
     85                        return symbol_get_addr(sd, sm, __tcb_get());
    7486        }
    7587
  • uspace/lib/c/generic/elf/elf_load.c

    r9259d20 r3e828ea  
    5353 * @param file File handle
    5454 * @param info Place to store ELF program information
    55  * @return EE_OK on success or an EE_x error code
     55 * @return EOK on success or an error code
    5656 */
    57 int elf_load(int file, elf_info_t *info)
     57errno_t elf_load(int file, elf_info_t *info)
    5858{
    5959#ifdef CONFIG_RTLD
    6060        rtld_t *env;
    6161#endif
    62         int rc;
     62        errno_t rc;
    6363
    6464        rc = elf_load_file(file, 0, &info->finfo);
    65         if (rc != EE_OK) {
     65        if (rc != EOK) {
    6666                DPRINTF("Failed to load executable '%s'.\n", file_name);
    6767                return rc;
     
    7272                DPRINTF("Binary is statically linked.\n");
    7373                info->env = NULL;
    74                 return EE_OK;
     74                return EOK;
    7575        }
    7676
     
    7979        DPRINTF("- prog dynamic: %p\n", info->finfo.dynamic);
    8080
    81         errno_t rc2 = rtld_prog_process(&info->finfo, &env);
    82         switch (rc2) {
    83         case EOK:
    84                 rc = EE_OK;
    85                 break;
    86         case ENOMEM:
    87                 rc = EE_MEMORY;
    88                 break;
    89         default:
    90                 DPRINTF("Unexpected error code from rtld_prog_process(): %s\n", str_error_name(rc2));
    91                 rc = EE_INVALID;
    92         }
    93 
     81        rc = rtld_prog_process(&info->finfo, &env);
    9482        info->env = env;
    9583#else
    96         rc = EE_UNSUPPORTED;
     84        rc = ENOTSUP;
    9785#endif
    9886        return rc;
  • uspace/lib/c/generic/elf/elf_mod.c

    r9259d20 r3e828ea  
    6464#define DPRINTF(...)
    6565
    66 static const char *error_codes[] = {
    67         "no error",
    68         "invalid image",
    69         "address space error",
    70         "incompatible image",
    71         "unsupported image type",
    72         "irrecoverable error",
    73         "file io error"
    74 };
    75 
    76 static unsigned int elf_load_module(elf_ld_t *elf);
    77 static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
    78 static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
     66static errno_t elf_load_module(elf_ld_t *elf);
     67static errno_t segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
     68static errno_t load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
    7969
    8070/** Load ELF binary from a file.
     
    9080 *                  extracted from the binary.
    9181 *
    92  * @return EE_OK on success or EE_xx error code.
    93  *
    94  */
    95 int elf_load_file(int file, eld_flags_t flags, elf_finfo_t *info)
     82 * @return EOK on success or an error code.
     83 *
     84 */
     85errno_t elf_load_file(int file, eld_flags_t flags, elf_finfo_t *info)
    9686{
    9787        elf_ld_t elf;
     
    10393        }
    10494        if (rc != EOK) {
    105                 return EE_IO;
     95                return rc;
    10696        }
    10797
     
    110100        elf.flags = flags;
    111101
    112         int ret = elf_load_module(&elf);
     102        rc = elf_load_module(&elf);
    113103
    114104        vfs_put(ofile);
    115         return ret;
    116 }
    117 
    118 int elf_load_file_name(const char *path, eld_flags_t flags, elf_finfo_t *info)
     105        return rc;
     106}
     107
     108errno_t elf_load_file_name(const char *path, eld_flags_t flags, elf_finfo_t *info)
    119109{
    120110        int file;
    121111        errno_t rc = vfs_lookup(path, 0, &file);
    122112        if (rc == EOK) {
    123                 int ret = elf_load_file(file, flags, info);
     113                rc = elf_load_file(file, flags, info);
    124114                vfs_put(file);
    125                 return ret;
     115                return rc;
    126116        } else {
    127                 return EE_IO;
     117                return EIO;
    128118        }
    129119}
     
    136126 *
    137127 * @param elf           Pointer to loader state buffer.
    138  * @return EE_OK on success or EE_xx error code.
    139  */
    140 static unsigned int elf_load_module(elf_ld_t *elf)
     128 * @return EOK on success or an error code.
     129 */
     130static errno_t elf_load_module(elf_ld_t *elf)
    141131{
    142132        elf_header_t header_buf;
     
    144134        aoff64_t pos = 0;
    145135        size_t nr;
    146         int i, ret;
     136        int i;
    147137        errno_t rc;
    148138
     
    150140        if (rc != EOK || nr != sizeof(elf_header_t)) {
    151141                DPRINTF("Read error.\n");
    152                 return EE_IO;
     142                return EIO;
    153143        }
    154144
     
    159149            header->e_ident[EI_MAG3] != ELFMAG3) {
    160150                DPRINTF("Invalid header.\n");
    161                 return EE_INVALID;
     151                return EINVAL;
    162152        }
    163153
     
    169159            header->e_ident[EI_CLASS] != ELF_CLASS) {
    170160                DPRINTF("Incompatible data/version/class.\n");
    171                 return EE_INCOMPATIBLE;
     161                return EINVAL;
    172162        }
    173163
     
    175165                DPRINTF("e_phentsize: %u != %zu\n", header->e_phentsize,
    176166                    sizeof(elf_segment_header_t));
    177                 return EE_INCOMPATIBLE;
     167                return EINVAL;
    178168        }
    179169
     
    181171        if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
    182172                DPRINTF("Object type %d is not supported\n", header->e_type);
    183                 return EE_UNSUPPORTED;
     173                return ENOTSUP;
    184174        }
    185175
    186176        if (header->e_phoff == 0) {
    187177                DPRINTF("Program header table is not present!\n");
    188                 return EE_UNSUPPORTED;
     178                return ENOTSUP;
    189179        }
    190180
     
    203193        if (phdr_len > sizeof(phdr)) {
    204194                DPRINTF("more than %d program headers\n", phdr_cap);
    205                 return EE_UNSUPPORTED;
     195                return ENOTSUP;
    206196        }
    207197
     
    210200        if (rc != EOK || nr != phdr_len) {
    211201                DPRINTF("Read error.\n");
    212                 return EE_IO;
     202                return EIO;
    213203        }
    214204
     
    231221        if (base_offset != 0) {
    232222                DPRINTF("ELF headers not present in the text segment.\n");
    233                 return EE_INVALID;
     223                return EINVAL;
    234224        }
    235225
     
    240230                if (module_base != 0) {
    241231                        DPRINTF("Unexpected shared object format.\n");
    242                         return EE_INVALID;
     232                        return EINVAL;
    243233                }
    244234
     
    258248                if (area == AS_MAP_FAILED) {
    259249                        DPRINTF("Can't find suitable memory area.\n");
    260                         return EE_MEMORY;
     250                        return ENOMEM;
    261251                }
    262252
     
    270260                        continue;
    271261
    272                 ret = load_segment(elf, &phdr[i]);
    273                 if (ret != EE_OK)
    274                         return ret;
     262                rc = load_segment(elf, &phdr[i]);
     263                if (rc != EOK)
     264                        return rc;
    275265        }
    276266
     
    292282                        continue;
    293283
    294                 ret = segment_header(elf, &phdr[i]);
    295                 if (ret != EE_OK)
    296                         return ret;
     284                rc = segment_header(elf, &phdr[i]);
     285                if (rc != EOK)
     286                        return rc;
    297287        }
    298288
     
    302292        DPRINTF("Done.\n");
    303293
    304         return EE_OK;
    305 }
    306 
    307 /** Print error message according to error code.
    308  *
    309  * @param rc Return code returned by elf_load().
    310  *
    311  * @return NULL terminated description of error.
    312  */
    313 const char *elf_error(unsigned int rc)
    314 {
    315         assert(rc < sizeof(error_codes) / sizeof(char *));
    316 
    317         return error_codes[rc];
     294        return EOK;
    318295}
    319296
     
    338315 * @param entry Segment header.
    339316 *
    340  * @return EE_OK on success, error code otherwise.
    341  */
    342 static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
     317 * @return EOK on success, error code otherwise.
     318 */
     319static errno_t segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
    343320{
    344321        switch (entry->p_type) {
     
    358335                if (entry->p_filesz == 0) {
    359336                        DPRINTF("Zero-sized ELF interp string.\n");
    360                         return EE_INVALID;
     337                        return EINVAL;
    361338                }
    362339                if (elf->info->interp[entry->p_filesz - 1] != '\0') {
    363340                        DPRINTF("Unterminated ELF interp string.\n");
    364                         return EE_INVALID;
     341                        return EINVAL;
    365342                }
    366343                DPRINTF("interpreter: \"%s\"\n", elf->info->interp);
     
    389366        default:
    390367                DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
    391                 return EE_UNSUPPORTED;
    392                 break;
    393         }
    394         return EE_OK;
     368                return ENOTSUP;
     369                break;
     370        }
     371        return EOK;
    395372}
    396373
     
    400377 * @param entry Program header entry describing segment to be loaded.
    401378 *
    402  * @return EE_OK on success, error code otherwise.
    403  */
    404 int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
     379 * @return EOK on success, error code otherwise.
     380 */
     381errno_t load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
    405382{
    406383        void *a;
     
    435412                            entry->p_offset % entry->p_align,
    436413                            seg_addr % entry->p_align, entry->p_align);
    437                         return EE_INVALID;
     414                        return EINVAL;
    438415                }
    439416        }
     
    466443                DPRINTF("memory mapping failed (%p, %zu)\n",
    467444                    (void *) (base + bias), mem_sz);
    468                 return EE_MEMORY;
     445                return ENOMEM;
    469446        }
    470447
     
    479456        if (rc != EOK || nr != entry->p_filesz) {
    480457                DPRINTF("read error\n");
    481                 return EE_IO;
     458                return EIO;
    482459        }
    483460
     
    487464         */
    488465        if ((elf->flags & ELDF_RW) != 0)
    489                 return EE_OK;
     466                return EOK;
    490467
    491468        DPRINTF("as_area_change_flags(%p, %x)\n",
     
    494471        if (rc != EOK) {
    495472                DPRINTF("Failed to set memory area flags.\n");
    496                 return EE_MEMORY;
     473                return ENOMEM;
    497474        }
    498475
     
    500477                /* Enforce SMC coherence for the segment */
    501478                if (smc_coherence(seg_ptr, entry->p_filesz))
    502                         return EE_MEMORY;
    503         }
    504 
    505         return EE_OK;
     479                        return ENOMEM;
     480        }
     481
     482        return EOK;
    506483}
    507484
  • uspace/lib/c/generic/private/stdio.h

    r9259d20 r3e828ea  
    4040#include <async.h>
    4141#include <stddef.h>
     42#include <offset.h>
    4243
    4344/** Maximum characters that can be pushed back by ungetc() */
     
    5455        int (*flush)(FILE *stream);
    5556} __stream_ops_t;
     57
     58enum __buffer_state {
     59        /** Buffer is empty */
     60        _bs_empty,
     61
     62        /** Buffer contains data to be written */
     63        _bs_write,
     64
     65        /** Buffer contains prefetched data for reading */
     66        _bs_read
     67};
    5668
    5769struct _IO_FILE {
     
    8799
    88100        /** Buffering type */
    89         enum _buffer_type btype;
     101        enum __buffer_type btype;
    90102
    91103        /** Buffer */
     
    96108
    97109        /** Buffer state */
    98         enum _buffer_state buf_state;
     110        enum __buffer_state buf_state;
    99111
    100112        /** Buffer I/O pointer */
  • uspace/lib/c/generic/rtld/module.c

    r9259d20 r3e828ea  
    6565
    6666        module = calloc(1, sizeof(module_t));
    67         if (module == NULL)
     67        if (module == NULL) {
     68                DPRINTF("malloc failed\n");
    6869                return ENOMEM;
     70        }
    6971
    7072        module->id = rtld_get_next_id(rtld);
     
    182184        char name_buf[NAME_BUF_SIZE];
    183185        module_t *m;
    184         int rc;
     186        errno_t rc;
    185187
    186188        m = calloc(1, sizeof(module_t));
    187189        if (m == NULL) {
    188                 printf("malloc failed\n");
    189                 exit(1);
     190                DPRINTF("malloc failed\n");
     191                goto error;
    190192        }
    191193
     
    197199
    198200        if (str_size(name) > NAME_BUF_SIZE - 2) {
    199                 printf("soname too long. increase NAME_BUF_SIZE\n");
    200                 exit(1);
     201                DPRINTF("soname too long. increase NAME_BUF_SIZE\n");
     202                goto error;
    201203        }
    202204
     
    208210
    209211        rc = elf_load_file_name(name_buf, RTLD_MODULE_LDF, &info);
    210         if (rc != EE_OK) {
    211                 printf("Failed to load '%s'\n", name_buf);
    212                 exit(1);
     212        if (rc != EOK) {
     213                DPRINTF("Failed to load '%s'\n", name_buf);
     214                goto error;
    213215        }
    214216
     
    218220
    219221        if (info.dynamic == NULL) {
    220                 printf("Error: '%s' is not a dynamically-linked object.\n",
     222                DPRINTF("Error: '%s' is not a dynamically-linked object.\n",
    221223                    name_buf);
    222                 exit(1);
     224                goto error;
    223225        }
    224226
     
    243245
    244246        return m;
     247
     248error:
     249        if (m)
     250                free(m);
     251
     252        return NULL;
    245253}
    246254
    247255/** Load all modules on which m (transitively) depends.
    248256 */
    249 void module_load_deps(module_t *m, mlflags_t flags)
     257errno_t module_load_deps(module_t *m, mlflags_t flags)
    250258{
    251259        elf_dyn_t *dp;
     
    274282                /* There are no dependencies, so we are done. */
    275283                m->deps = NULL;
    276                 return;
     284                return EOK;
    277285        }
    278286
    279287        m->deps = malloc(n * sizeof(module_t *));
    280288        if (!m->deps) {
    281                 printf("malloc failed\n");
    282                 exit(1);
     289                DPRINTF("malloc failed\n");
     290                return ENOMEM;
    283291        }
    284292
     
    294302                        if (!dm) {
    295303                                dm = module_load(m->rtld, dep_name, flags);
    296                                 module_load_deps(dm, flags);
     304                                if (!dm) {
     305                                        return EINVAL;
     306                                }
     307
     308                                errno_t rc = module_load_deps(dm, flags);
     309                                if (rc != EOK) {
     310                                        return rc;
     311                                }
    297312                        }
    298313
     
    302317                ++dp;
    303318        }
     319
     320        return EOK;
    304321}
    305322
  • uspace/lib/c/generic/rtld/rtld.c

    r9259d20 r3e828ea  
    125125
    126126        DPRINTF("Load all program dependencies\n");
    127         module_load_deps(prog, 0);
     127        errno_t rc = module_load_deps(prog, 0);
     128        if (rc != EOK) {
     129                return rc;
     130        }
    128131
    129132        /* Compute static TLS size */
  • uspace/lib/c/generic/str.c

    r9259d20 r3e828ea  
    14711471        *end = '\0';
    14721472        return start;
    1473 }
    1474 
    1475 /** Convert string to uint64_t (internal variant).
    1476  *
    1477  * @param nptr   Pointer to string.
    1478  * @param endptr Pointer to the first invalid character is stored here.
    1479  * @param base   Zero or number between 2 and 36 inclusive.
    1480  * @param neg    Indication of unary minus is stored here.
    1481  * @apram result Result of the conversion.
    1482  *
    1483  * @return EOK if conversion was successful.
    1484  *
    1485  */
    1486 static errno_t str_uint(const char *nptr, char **endptr, unsigned int base,
    1487     bool *neg, uint64_t *result)
    1488 {
    1489         assert(endptr != NULL);
    1490         assert(neg != NULL);
    1491         assert(result != NULL);
    1492 
    1493         *neg = false;
    1494         const char *str = nptr;
    1495 
    1496         /* Ignore leading whitespace */
    1497         while (isspace(*str))
    1498                 str++;
    1499 
    1500         if (*str == '-') {
    1501                 *neg = true;
    1502                 str++;
    1503         } else if (*str == '+')
    1504                 str++;
    1505 
    1506         if (base == 0) {
    1507                 /* Decode base if not specified */
    1508                 base = 10;
    1509 
    1510                 if (*str == '0') {
    1511                         base = 8;
    1512                         str++;
    1513 
    1514                         switch (*str) {
    1515                         case 'b':
    1516                         case 'B':
    1517                                 base = 2;
    1518                                 str++;
    1519                                 break;
    1520                         case 'o':
    1521                         case 'O':
    1522                                 base = 8;
    1523                                 str++;
    1524                                 break;
    1525                         case 'd':
    1526                         case 'D':
    1527                         case 't':
    1528                         case 'T':
    1529                                 base = 10;
    1530                                 str++;
    1531                                 break;
    1532                         case 'x':
    1533                         case 'X':
    1534                                 base = 16;
    1535                                 str++;
    1536                                 break;
    1537                         default:
    1538                                 str--;
    1539                         }
    1540                 }
    1541         } else {
    1542                 /* Check base range */
    1543                 if ((base < 2) || (base > 36)) {
    1544                         *endptr = (char *) str;
    1545                         return EINVAL;
    1546                 }
    1547         }
    1548 
    1549         *result = 0;
    1550         const char *startstr = str;
    1551 
    1552         while (*str != 0) {
    1553                 unsigned int digit;
    1554 
    1555                 if ((*str >= 'a') && (*str <= 'z'))
    1556                         digit = *str - 'a' + 10;
    1557                 else if ((*str >= 'A') && (*str <= 'Z'))
    1558                         digit = *str - 'A' + 10;
    1559                 else if ((*str >= '0') && (*str <= '9'))
    1560                         digit = *str - '0';
    1561                 else
    1562                         break;
    1563 
    1564                 if (digit >= base)
    1565                         break;
    1566 
    1567                 uint64_t prev = *result;
    1568                 *result = (*result) * base + digit;
    1569 
    1570                 if (*result < prev) {
    1571                         /* Overflow */
    1572                         *endptr = (char *) str;
    1573                         return EOVERFLOW;
    1574                 }
    1575 
    1576                 str++;
    1577         }
    1578 
    1579         if (str == startstr) {
    1580                 /*
    1581                  * No digits were decoded => first invalid character is
    1582                  * the first character of the string.
    1583                  */
    1584                 str = nptr;
    1585         }
    1586 
    1587         *endptr = (char *) str;
    1588 
    1589         if (str == nptr)
    1590                 return EINVAL;
    1591 
    1592         return EOK;
    1593 }
    1594 
    1595 /** Convert string to uint8_t.
    1596  *
    1597  * @param nptr   Pointer to string.
    1598  * @param endptr If not NULL, pointer to the first invalid character
    1599  *               is stored here.
    1600  * @param base   Zero or number between 2 and 36 inclusive.
    1601  * @param strict Do not allow any trailing characters.
    1602  * @param result Result of the conversion.
    1603  *
    1604  * @return EOK if conversion was successful.
    1605  *
    1606  */
    1607 errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
    1608     bool strict, uint8_t *result)
    1609 {
    1610         assert(result != NULL);
    1611 
    1612         bool neg;
    1613         char *lendptr;
    1614         uint64_t res;
    1615         errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
    1616 
    1617         if (endptr != NULL)
    1618                 *endptr = (char *) lendptr;
    1619 
    1620         if (ret != EOK)
    1621                 return ret;
    1622 
    1623         /* Do not allow negative values */
    1624         if (neg)
    1625                 return EINVAL;
    1626 
    1627         /*
    1628          * Check whether we are at the end of
    1629          * the string in strict mode
    1630          */
    1631         if ((strict) && (*lendptr != 0))
    1632                 return EINVAL;
    1633 
    1634         /* Check for overflow */
    1635         uint8_t _res = (uint8_t) res;
    1636         if (_res != res)
    1637                 return EOVERFLOW;
    1638 
    1639         *result = _res;
    1640 
    1641         return EOK;
    1642 }
    1643 
    1644 /** Convert string to uint16_t.
    1645  *
    1646  * @param nptr   Pointer to string.
    1647  * @param endptr If not NULL, pointer to the first invalid character
    1648  *               is stored here.
    1649  * @param base   Zero or number between 2 and 36 inclusive.
    1650  * @param strict Do not allow any trailing characters.
    1651  * @param result Result of the conversion.
    1652  *
    1653  * @return EOK if conversion was successful.
    1654  *
    1655  */
    1656 errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
    1657     bool strict, uint16_t *result)
    1658 {
    1659         assert(result != NULL);
    1660 
    1661         bool neg;
    1662         char *lendptr;
    1663         uint64_t res;
    1664         errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
    1665 
    1666         if (endptr != NULL)
    1667                 *endptr = (char *) lendptr;
    1668 
    1669         if (ret != EOK)
    1670                 return ret;
    1671 
    1672         /* Do not allow negative values */
    1673         if (neg)
    1674                 return EINVAL;
    1675 
    1676         /*
    1677          * Check whether we are at the end of
    1678          * the string in strict mode
    1679          */
    1680         if ((strict) && (*lendptr != 0))
    1681                 return EINVAL;
    1682 
    1683         /* Check for overflow */
    1684         uint16_t _res = (uint16_t) res;
    1685         if (_res != res)
    1686                 return EOVERFLOW;
    1687 
    1688         *result = _res;
    1689 
    1690         return EOK;
    1691 }
    1692 
    1693 /** Convert string to uint32_t.
    1694  *
    1695  * @param nptr   Pointer to string.
    1696  * @param endptr If not NULL, pointer to the first invalid character
    1697  *               is stored here.
    1698  * @param base   Zero or number between 2 and 36 inclusive.
    1699  * @param strict Do not allow any trailing characters.
    1700  * @param result Result of the conversion.
    1701  *
    1702  * @return EOK if conversion was successful.
    1703  *
    1704  */
    1705 errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
    1706     bool strict, uint32_t *result)
    1707 {
    1708         assert(result != NULL);
    1709 
    1710         bool neg;
    1711         char *lendptr;
    1712         uint64_t res;
    1713         errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
    1714 
    1715         if (endptr != NULL)
    1716                 *endptr = (char *) lendptr;
    1717 
    1718         if (ret != EOK)
    1719                 return ret;
    1720 
    1721         /* Do not allow negative values */
    1722         if (neg)
    1723                 return EINVAL;
    1724 
    1725         /*
    1726          * Check whether we are at the end of
    1727          * the string in strict mode
    1728          */
    1729         if ((strict) && (*lendptr != 0))
    1730                 return EINVAL;
    1731 
    1732         /* Check for overflow */
    1733         uint32_t _res = (uint32_t) res;
    1734         if (_res != res)
    1735                 return EOVERFLOW;
    1736 
    1737         *result = _res;
    1738 
    1739         return EOK;
    1740 }
    1741 
    1742 /** Convert string to uint64_t.
    1743  *
    1744  * @param nptr   Pointer to string.
    1745  * @param endptr If not NULL, pointer to the first invalid character
    1746  *               is stored here.
    1747  * @param base   Zero or number between 2 and 36 inclusive.
    1748  * @param strict Do not allow any trailing characters.
    1749  * @param result Result of the conversion.
    1750  *
    1751  * @return EOK if conversion was successful.
    1752  *
    1753  */
    1754 errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
    1755     bool strict, uint64_t *result)
    1756 {
    1757         assert(result != NULL);
    1758 
    1759         bool neg;
    1760         char *lendptr;
    1761         errno_t ret = str_uint(nptr, &lendptr, base, &neg, result);
    1762 
    1763         if (endptr != NULL)
    1764                 *endptr = (char *) lendptr;
    1765 
    1766         if (ret != EOK)
    1767                 return ret;
    1768 
    1769         /* Do not allow negative values */
    1770         if (neg)
    1771                 return EINVAL;
    1772 
    1773         /*
    1774          * Check whether we are at the end of
    1775          * the string in strict mode
    1776          */
    1777         if ((strict) && (*lendptr != 0))
    1778                 return EINVAL;
    1779 
    1780         return EOK;
    1781 }
    1782 
    1783 /** Convert string to int64_t.
    1784  *
    1785  * @param nptr   Pointer to string.
    1786  * @param endptr If not NULL, pointer to the first invalid character
    1787  *               is stored here.
    1788  * @param base   Zero or number between 2 and 36 inclusive.
    1789  * @param strict Do not allow any trailing characters.
    1790  * @param result Result of the conversion.
    1791  *
    1792  * @return EOK if conversion was successful.
    1793  *
    1794  */
    1795 int str_int64_t(const char *nptr, const char **endptr, unsigned int base,
    1796     bool strict, int64_t *result)
    1797 {
    1798         assert(result != NULL);
    1799 
    1800         bool neg;
    1801         char *lendptr;
    1802         uint64_t unsigned_result;
    1803         int ret = str_uint(nptr, &lendptr, base, &neg, &unsigned_result);
    1804 
    1805         if (endptr != NULL)
    1806                 *endptr = (char *) lendptr;
    1807 
    1808         if (ret != EOK)
    1809                 return ret;
    1810 
    1811         /* Do not allow negative values */
    1812         if (neg) {
    1813                 if (unsigned_result == UINT64_MAX)
    1814                         return EINVAL;
    1815 
    1816                 *result = -(int64_t) unsigned_result;
    1817         } else
    1818                 *result = unsigned_result;
    1819 
    1820         /*
    1821          * Check whether we are at the end of
    1822          * the string in strict mode
    1823          */
    1824         if ((strict) && (*lendptr != 0))
    1825                 return EINVAL;
    1826 
    1827         return EOK;
    1828 }
    1829 
    1830 /** Convert string to size_t.
    1831  *
    1832  * @param nptr   Pointer to string.
    1833  * @param endptr If not NULL, pointer to the first invalid character
    1834  *               is stored here.
    1835  * @param base   Zero or number between 2 and 36 inclusive.
    1836  * @param strict Do not allow any trailing characters.
    1837  * @param result Result of the conversion.
    1838  *
    1839  * @return EOK if conversion was successful.
    1840  *
    1841  */
    1842 errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
    1843     bool strict, size_t *result)
    1844 {
    1845         assert(result != NULL);
    1846 
    1847         bool neg;
    1848         char *lendptr;
    1849         uint64_t res;
    1850         errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
    1851 
    1852         if (endptr != NULL)
    1853                 *endptr = (char *) lendptr;
    1854 
    1855         if (ret != EOK)
    1856                 return ret;
    1857 
    1858         /* Do not allow negative values */
    1859         if (neg)
    1860                 return EINVAL;
    1861 
    1862         /*
    1863          * Check whether we are at the end of
    1864          * the string in strict mode
    1865          */
    1866         if ((strict) && (*lendptr != 0))
    1867                 return EINVAL;
    1868 
    1869         /* Check for overflow */
    1870         size_t _res = (size_t) res;
    1871         if (_res != res)
    1872                 return EOVERFLOW;
    1873 
    1874         *result = _res;
    1875 
    1876         return EOK;
    18771473}
    18781474
  • uspace/lib/c/generic/strtol.c

    r9259d20 r3e828ea  
    4444#include <stdbool.h>
    4545#include <stdlib.h>
    46 
    47 // TODO: unit tests
     46#include <str.h>
     47
     48// FIXME: The original HelenOS functions return EOVERFLOW instead
     49//        of ERANGE. It's a pointless distinction from standard functions,
     50//        so we should change that. Beware the callers though.
     51
     52// TODO: more unit tests
    4853
    4954static inline int _digit_value(int c)
     
    6974}
    7075
     76static inline int _prefixbase(const char *restrict *nptrptr, bool nonstd)
     77{
     78        const char *nptr = *nptrptr;
     79
     80        if (nptr[0] != '0')
     81                return 10;
     82
     83        if (nptr[1] == 'x' || nptr[1] == 'X') {
     84                if (_digit_value(nptr[2]) < 16) {
     85                        *nptrptr += 2;
     86                        return 16;
     87                }
     88        }
     89
     90        if (nonstd) {
     91                switch (nptr[1]) {
     92                case 'b':
     93                case 'B':
     94                        if (_digit_value(nptr[2]) < 2) {
     95                                *nptrptr += 2;
     96                                return 2;
     97                        }
     98                        break;
     99                case 'o':
     100                case 'O':
     101                        if (_digit_value(nptr[2]) < 8) {
     102                                *nptrptr += 2;
     103                                return 8;
     104                        }
     105                        break;
     106                case 'd':
     107                case 'D':
     108                case 't':
     109                case 'T':
     110                        if (_digit_value(nptr[2]) < 10) {
     111                                *nptrptr += 2;
     112                                return 10;
     113                        }
     114                        break;
     115                }
     116        }
     117
     118        return 8;
     119}
     120
    71121static inline uintmax_t _strtoumax(
    72122    const char *restrict nptr, char **restrict endptr, int base,
    73     bool *restrict sgn)
     123    bool *restrict sgn, errno_t *err, bool nonstd)
    74124{
    75125        assert(nptr != NULL);
    76126        assert(sgn != NULL);
     127
     128        const char *first = nptr;
    77129
    78130        /* Skip leading whitespace. */
     
    96148        /* Figure out the base. */
    97149
    98         if (base == 0) {
    99                 if (*nptr == '0') {
    100                         if (tolower(nptr[1]) == 'x') {
    101                                 /* 0x... is hex. */
    102                                 base = 16;
    103                                 nptr += 2;
    104                         } else {
    105                                 /* 0... is octal. */
    106                                 base = 8;
    107                         }
    108                 } else {
    109                         /* Anything else is decimal by default. */
    110                         base = 10;
    111                 }
    112         } else if (base == 16) {
    113                 /* Allow hex number to be prefixed with "0x". */
    114                 if (nptr[0] == '0' && tolower(nptr[1]) == 'x') {
     150        if (base == 0)
     151                base = _prefixbase(&nptr, nonstd);
     152
     153        if (base == 16 && !nonstd) {
     154                /*
     155                 * Standard strto* functions allow hexadecimal prefix to be
     156                 * present when base is explicitly set to 16.
     157                 * Our nonstandard str_* functions don't allow it.
     158                 * I don't know if that is intended, just matching the original
     159                 * functionality here.
     160                 */
     161
     162                if (nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X') &&
     163                    _digit_value(nptr[2]) < base)
    115164                        nptr += 2;
    116                 }
    117         } else if (base < 0 || base == 1 || base > 36) {
    118                 errno = EINVAL;
     165        }
     166
     167        if (base < 2 || base > 36) {
     168                *err = EINVAL;
    119169                return 0;
    120170        }
    121171
    122         /* Read the value. */
     172        /* Must be at least one digit. */
     173
     174        if (_digit_value(*nptr) >= base) {
     175                /* No digits on input. */
     176                if (endptr != NULL)
     177                        *endptr = (char *) first;
     178                return 0;
     179        }
     180
     181        /* Read the value.  */
    123182
    124183        uintmax_t result = 0;
     
    127186
    128187        while (digit = _digit_value(*nptr), digit < base) {
    129 
    130188                if (result > max ||
    131189                    __builtin_add_overflow(result * base, digit, &result)) {
    132190
    133                         errno = ERANGE;
     191                        *err = nonstd ? EOVERFLOW : ERANGE;
    134192                        result = UINTMAX_MAX;
    135193                        break;
     
    145203                 * Move the pointer to the end of the number,
    146204                 * in case it isn't there already.
     205                 * This can happen when the number has legal formatting,
     206                 * but is out of range of the target type.
    147207                 */
    148208                while (_digit_value(*nptr) < base) {
     
    157217
    158218static inline intmax_t _strtosigned(const char *nptr, char **endptr, int base,
    159     intmax_t min, intmax_t max)
     219    intmax_t min, intmax_t max, errno_t *err, bool nonstd)
    160220{
    161221        bool sgn = false;
    162         uintmax_t number = _strtoumax(nptr, endptr, base, &sgn);
     222        uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
    163223
    164224        if (number > (uintmax_t) max) {
     
    167227                }
    168228
    169                 errno = ERANGE;
     229                *err = nonstd ? EOVERFLOW : ERANGE;
    170230                return (sgn ? min : max);
    171231        }
     
    175235
    176236static inline uintmax_t _strtounsigned(const char *nptr, char **endptr, int base,
    177     uintmax_t max)
     237    uintmax_t max, errno_t *err, bool nonstd)
    178238{
    179239        bool sgn = false;
    180         uintmax_t number = _strtoumax(nptr, endptr, base, &sgn);
    181 
    182         if (sgn) {
    183                 if (number == 0) {
    184                         return 0;
    185                 } else {
    186                         errno = ERANGE;
    187                         return max;
    188                 }
     240        uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
     241
     242        if (nonstd && sgn) {
     243                /* Do not allow negative values */
     244                *err = EINVAL;
     245                return 0;
    189246        }
    190247
    191248        if (number > max) {
    192                 errno = ERANGE;
     249                *err = nonstd ? EOVERFLOW : ERANGE;
    193250                return max;
    194251        }
    195252
    196         return number;
     253        return (sgn ? -number : number);
    197254}
    198255
     
    212269long strtol(const char *nptr, char **endptr, int base)
    213270{
    214         return _strtosigned(nptr, endptr, base, LONG_MIN, LONG_MAX);
     271        return _strtosigned(nptr, endptr, base, LONG_MIN, LONG_MAX, &errno, false);
    215272}
    216273
     
    230287unsigned long strtoul(const char *nptr, char **endptr, int base)
    231288{
    232         return _strtounsigned(nptr, endptr, base, ULONG_MAX);
     289        return _strtounsigned(nptr, endptr, base, ULONG_MAX, &errno, false);
    233290}
    234291
    235292long long strtoll(const char *nptr, char **endptr, int base)
    236293{
    237         return _strtosigned(nptr, endptr, base, LLONG_MIN, LLONG_MAX);
     294        return _strtosigned(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &errno, false);
    238295}
    239296
    240297unsigned long long strtoull(const char *nptr, char **endptr, int base)
    241298{
    242         return _strtounsigned(nptr, endptr, base, ULLONG_MAX);
     299        return _strtounsigned(nptr, endptr, base, ULLONG_MAX, &errno, false);
    243300}
    244301
    245302intmax_t strtoimax(const char *nptr, char **endptr, int base)
    246303{
    247         return _strtosigned(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX);
     304        return _strtosigned(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX, &errno, false);
    248305}
    249306
    250307uintmax_t strtoumax(const char *nptr, char **endptr, int base)
    251308{
    252         return _strtounsigned(nptr, endptr, base, UINTMAX_MAX);
     309        return _strtounsigned(nptr, endptr, base, UINTMAX_MAX, &errno, false);
    253310}
    254311
     
    268325}
    269326
     327/** Convert string to uint8_t.
     328 *
     329 * @param nptr   Pointer to string.
     330 * @param endptr If not NULL, pointer to the first invalid character
     331 *               is stored here.
     332 * @param base   Zero or number between 2 and 36 inclusive.
     333 * @param strict Do not allow any trailing characters.
     334 * @param result Result of the conversion.
     335 *
     336 * @return EOK if conversion was successful.
     337 *
     338 */
     339errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
     340    bool strict, uint8_t *result)
     341{
     342        assert(result != NULL);
     343
     344        errno_t rc = EOK;
     345        char *lendptr = (char *) nptr;
     346
     347        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT8_MAX, &rc, true);
     348
     349        if (endptr)
     350                *endptr = lendptr;
     351
     352        if (rc != EOK)
     353                return rc;
     354
     355        if (strict && *lendptr != '\0')
     356                return EINVAL;
     357
     358        *result = r;
     359        return EOK;
     360}
     361
     362/** Convert string to uint16_t.
     363 *
     364 * @param nptr   Pointer to string.
     365 * @param endptr If not NULL, pointer to the first invalid character
     366 *               is stored here.
     367 * @param base   Zero or number between 2 and 36 inclusive.
     368 * @param strict Do not allow any trailing characters.
     369 * @param result Result of the conversion.
     370 *
     371 * @return EOK if conversion was successful.
     372 *
     373 */
     374errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
     375    bool strict, uint16_t *result)
     376{
     377        assert(result != NULL);
     378
     379        errno_t rc = EOK;
     380        char *lendptr = (char *) nptr;
     381
     382        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT16_MAX, &rc, true);
     383
     384        if (endptr)
     385                *endptr = lendptr;
     386
     387        if (rc != EOK)
     388                return rc;
     389
     390        if (strict && *lendptr != '\0')
     391                return EINVAL;
     392
     393        *result = r;
     394        return EOK;
     395}
     396
     397/** Convert string to uint32_t.
     398 *
     399 * @param nptr   Pointer to string.
     400 * @param endptr If not NULL, pointer to the first invalid character
     401 *               is stored here.
     402 * @param base   Zero or number between 2 and 36 inclusive.
     403 * @param strict Do not allow any trailing characters.
     404 * @param result Result of the conversion.
     405 *
     406 * @return EOK if conversion was successful.
     407 *
     408 */
     409errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
     410    bool strict, uint32_t *result)
     411{
     412        assert(result != NULL);
     413
     414        errno_t rc = EOK;
     415        char *lendptr = (char *) nptr;
     416
     417        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT32_MAX, &rc, true);
     418
     419        if (endptr)
     420                *endptr = lendptr;
     421
     422        if (rc != EOK)
     423                return rc;
     424
     425        if (strict && *lendptr != '\0')
     426                return EINVAL;
     427
     428        *result = r;
     429        return EOK;
     430}
     431
     432/** Convert string to uint64_t.
     433 *
     434 * @param nptr   Pointer to string.
     435 * @param endptr If not NULL, pointer to the first invalid character
     436 *               is stored here.
     437 * @param base   Zero or number between 2 and 36 inclusive.
     438 * @param strict Do not allow any trailing characters.
     439 * @param result Result of the conversion.
     440 *
     441 * @return EOK if conversion was successful.
     442 *
     443 */
     444errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
     445    bool strict, uint64_t *result)
     446{
     447        assert(result != NULL);
     448
     449        errno_t rc = EOK;
     450        char *lendptr = (char *) nptr;
     451
     452        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT64_MAX, &rc, true);
     453
     454        if (endptr)
     455                *endptr = lendptr;
     456
     457        if (rc != EOK)
     458                return rc;
     459
     460        if (strict && *lendptr != '\0')
     461                return EINVAL;
     462
     463        *result = r;
     464        return EOK;
     465}
     466
     467/** Convert string to int64_t.
     468 *
     469 * @param nptr   Pointer to string.
     470 * @param endptr If not NULL, pointer to the first invalid character
     471 *               is stored here.
     472 * @param base   Zero or number between 2 and 36 inclusive.
     473 * @param strict Do not allow any trailing characters.
     474 * @param result Result of the conversion.
     475 *
     476 * @return EOK if conversion was successful.
     477 *
     478 */
     479errno_t str_int64_t(const char *nptr, const char **endptr, unsigned int base,
     480    bool strict, int64_t *result)
     481{
     482        assert(result != NULL);
     483
     484        errno_t rc = EOK;
     485        char *lendptr = (char *) nptr;
     486
     487        intmax_t r = _strtosigned(nptr, &lendptr, base, INT64_MIN, INT64_MAX, &rc, true);
     488
     489        if (endptr)
     490                *endptr = lendptr;
     491
     492        if (rc != EOK)
     493                return rc;
     494
     495        if (strict && *lendptr != '\0')
     496                return EINVAL;
     497
     498        *result = r;
     499        return EOK;
     500}
     501
     502/** Convert string to size_t.
     503 *
     504 * @param nptr   Pointer to string.
     505 * @param endptr If not NULL, pointer to the first invalid character
     506 *               is stored here.
     507 * @param base   Zero or number between 2 and 36 inclusive.
     508 * @param strict Do not allow any trailing characters.
     509 * @param result Result of the conversion.
     510 *
     511 * @return EOK if conversion was successful.
     512 *
     513 */
     514errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
     515    bool strict, size_t *result)
     516{
     517        assert(result != NULL);
     518
     519        errno_t rc = EOK;
     520        char *lendptr = (char *) nptr;
     521
     522        uintmax_t r = _strtounsigned(nptr, &lendptr, base, SIZE_MAX, &rc, true);
     523
     524        if (endptr)
     525                *endptr = lendptr;
     526
     527        if (rc != EOK)
     528                return rc;
     529
     530        if (strict && *lendptr != '\0')
     531                return EINVAL;
     532
     533        *result = r;
     534        return EOK;
     535}
     536
    270537/** @}
    271538 */
  • uspace/lib/c/generic/ubsan.c

    r9259d20 r3e828ea  
    3535};
    3636
     37struct type_mismatch_data_v1 {
     38        struct source_location loc;
     39        struct type_descriptor *type;
     40        unsigned char log_alignment;
     41        unsigned char type_check_kind;
     42};
     43
    3744struct overflow_data {
    3845        struct source_location loc;
     
    7380        struct source_location loc;
    7481        struct source_location attr_loc;
     82};
     83
     84struct pointer_overflow_data {
     85        struct source_location loc;
    7586};
    7687
     
    8192 */
    8293void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, unsigned long ptr);
     94void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data, unsigned long ptr);
    8395void __ubsan_handle_add_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
    8496void __ubsan_handle_sub_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
     
    99111void __ubsan_handle_nonnull_return(struct nonnull_return_data *data);
    100112void __ubsan_handle_builtin_unreachable(struct unreachable_data *data);
     113void __ubsan_handle_pointer_overflow(struct pointer_overflow_data *data,
     114    unsigned long base, unsigned long result);
    101115
    102116static void print_loc(const char *func, struct source_location *loc)
     
    121135}
    122136
     137void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
     138    unsigned long ptr)
     139{
     140        print_loc(__func__, &data->loc);
     141        PRINTF("Type: %s, alignment: %hhu, type_check_kind: %hhu\n",
     142            data->type->type_name, data->log_alignment, data->type_check_kind);
     143        ubsan_panic();
     144}
     145
    123146void __ubsan_handle_add_overflow(struct overflow_data *data,
    124147    unsigned long lhs,
     
    228251        ubsan_panic();
    229252}
     253
     254void __ubsan_handle_pointer_overflow(struct pointer_overflow_data *data,
     255    unsigned long base, unsigned long result)
     256{
     257        print_loc(__func__, &data->loc);
     258        ubsan_panic();
     259}
Note: See TracChangeset for help on using the changeset viewer.