crypto/x509/by_dir.c:349: error: INTEGER_OVERFLOW_L2
  ([0, +oo] - 1):unsigned64 by call to `BIO_snprintf`.
Showing all 12 steps of the trace


crypto/x509/by_dir.c:305:14: Call
303.           ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
304.           j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
305.           if (!BUF_MEM_grow(b, j)) {
                    ^
306.               X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
307.               goto finish;

crypto/buffer/buffer.c:122:1: Parameter `len`
  120.   }
  121.   
  122. > size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
  123.   {
  124.       char *ret;

crypto/x509/by_dir.c:305:14: Call
303.           ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
304.           j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
305.           if (!BUF_MEM_grow(b, j)) {
                    ^
306.               X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
307.               goto finish;

crypto/buffer/buffer.c:122:1: Parameter `len`
  120.   }
  121.   
  122. > size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
  123.   {
  124.       char *ret;

crypto/x509/by_dir.c:349:17: Call
347.                                "%s%08lx.%s%d", ent->dir, h, postfix, k);
348.               } else {
349.                   BIO_snprintf(b->data, b->max,
                       ^
350.                                "%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);
351.               }

crypto/bio/b_print.c:788:1: Parameter `n`
  786.    * function should be renamed, but to what?)
  787.    */
  788. > int BIO_snprintf(char *buf, size_t n, const char *format, ...)
  789.   {
  790.       va_list args;

crypto/bio/b_print.c:795:11: Call
  793.       va_start(args, format);
  794.   
  795.       ret = BIO_vsnprintf(buf, n, format, args);
                   ^
  796.   
  797.       va_end(args);

crypto/bio/b_print.c:801:1: Parameter `n`
    799.   }
    800.   
    801. > int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
    802.   {
    803.       size_t retlen;

crypto/bio/b_print.c:806:5: Call
    804.       int truncated;
    805.   
    806.       _dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
               ^
    807.   
    808.       if (truncated)

crypto/bio/b_print.c:168:1: <LHS trace>
166.   #define OSSL_MAX(p,q) ((p >= q) ? p : q)
167.   
168. > static void
169.   _dopr(char **sbuffer,
170.         char **buffer,

crypto/bio/b_print.c:168:1: Parameter `*maxlen`
      166.   #define OSSL_MAX(p,q) ((p >= q) ? p : q)
      167.   
      168. > static void
      169.   _dopr(char **sbuffer,
      170.         char **buffer,

crypto/bio/b_print.c:418:19: Binary operation: ([0, +oo] - 1):unsigned64 by call to `BIO_snprintf` 
      416.           }
      417.       }
      418.       *truncated = (currlen > *maxlen - 1);
                               ^
      419.       if (*truncated)
      420.           currlen = *maxlen - 1;

static void
_dopr(char **sbuffer,
      char **buffer,
      size_t *maxlen,
      size_t *retlen, int *truncated, const char *format, va_list args)
{
    char ch;
    LLONG value;
    LDOUBLE fvalue;
    char *strvalue;
    int min;
    int max;
    int state;
    int flags;
    int cflags;
    size_t currlen;
    state = DP_S_DEFAULT;
    flags = currlen = cflags = min = 0;
    max = -1;
    ch = *format++;
    while (state != DP_S_DONE) {
        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
            state = DP_S_DONE;
        switch (state) {
        case DP_S_DEFAULT:
            if (ch == '%')
                state = DP_S_FLAGS;
            else
                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
            ch = *format++;
            break;
        case DP_S_FLAGS:
            switch (ch) {
            case '-':
                flags |= DP_F_MINUS;
                ch = *format++;
                break;
            case '+':
                flags |= DP_F_PLUS;
                ch = *format++;
                break;
            case ' ':
                flags |= DP_F_SPACE;
                ch = *format++;
                break;
            case '#':
                flags |= DP_F_NUM;
                ch = *format++;
                break;
            case '0':
                flags |= DP_F_ZERO;
                ch = *format++;
                break;
            default:
                state = DP_S_MIN;
                break;
            }
            break;
        case DP_S_MIN:
            if (isdigit((unsigned char)ch)) {
                min = 10 * min + char_to_int(ch);
                ch = *format++;
            } else if (ch == '*') {
                min = va_arg(args, int);
                ch = *format++;
                state = DP_S_DOT;
            } else
                state = DP_S_DOT;
            break;
        case DP_S_DOT:
            if (ch == '.') {
                state = DP_S_MAX;
                ch = *format++;
            } else
                state = DP_S_MOD;
            break;
        case DP_S_MAX:
            if (isdigit((unsigned char)ch)) {
                if (max < 0)
                    max = 0;
                max = 10 * max + char_to_int(ch);
                ch = *format++;
            } else if (ch == '*') {
                max = va_arg(args, int);
                ch = *format++;
                state = DP_S_MOD;
            } else
                state = DP_S_MOD;
            break;
        case DP_S_MOD:
            switch (ch) {
            case 'h':
                cflags = DP_C_SHORT;
                ch = *format++;
                break;
            case 'l':
                if (*format == 'l') {
                    cflags = DP_C_LLONG;
                    format++;
                } else
                    cflags = DP_C_LONG;
                ch = *format++;
                break;
            case 'q':
                cflags = DP_C_LLONG;
                ch = *format++;
                break;
            case 'L':
                cflags = DP_C_LDOUBLE;
                ch = *format++;
                break;
            default:
                break;
            }
            state = DP_S_CONV;
            break;
        case DP_S_CONV:
            switch (ch) {
            case 'd':
            case 'i':
                switch (cflags) {
                case DP_C_SHORT:
                    value = (short int)va_arg(args, int);
                    break;
                case DP_C_LONG:
                    value = va_arg(args, long int);
                    break;
                case DP_C_LLONG:
                    value = va_arg(args, LLONG);
                    break;
                default:
                    value = va_arg(args, int);
                    break;
                }
                fmtint(sbuffer, buffer, &currlen, maxlen,
                       value, 10, min, max, flags);
                break;
            case 'X':
                flags |= DP_F_UP;
            case 'x':
            case 'o':
            case 'u':
                flags |= DP_F_UNSIGNED;
                switch (cflags) {
                case DP_C_SHORT:
                    value = (unsigned short int)va_arg(args, unsigned int);
                    break;
                case DP_C_LONG:
                    value = (LLONG) va_arg(args, unsigned long int);
                    break;
                case DP_C_LLONG:
                    value = va_arg(args, unsigned LLONG);
                    break;
                default:
                    value = (LLONG) va_arg(args, unsigned int);
                    break;
                }
                fmtint(sbuffer, buffer, &currlen, maxlen, value,
                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
                       min, max, flags);
                break;
            case 'f':
                if (cflags == DP_C_LDOUBLE)
                    fvalue = va_arg(args, LDOUBLE);
                else
                    fvalue = va_arg(args, double);
                fmtfp(sbuffer, buffer, &currlen, maxlen,
                      fvalue, min, max, flags);
                break;
            case 'E':
                flags |= DP_F_UP;
            case 'e':
                if (cflags == DP_C_LDOUBLE)
                    fvalue = va_arg(args, LDOUBLE);
                else
                    fvalue = va_arg(args, double);
                break;
            case 'G':
                flags |= DP_F_UP;
            case 'g':
                if (cflags == DP_C_LDOUBLE)
                    fvalue = va_arg(args, LDOUBLE);
                else
                    fvalue = va_arg(args, double);
                break;
            case 'c':
                doapr_outch(sbuffer, buffer, &currlen, maxlen,
                            va_arg(args, int));
                break;
            case 's':
                strvalue = va_arg(args, char *);
                if (max < 0) {
                    if (buffer)
                        max = INT_MAX;
                    else
                        max = *maxlen;
                }
                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
                       flags, min, max);
                break;
            case 'p':
                value = (long)va_arg(args, void *);
                fmtint(sbuffer, buffer, &currlen, maxlen,
                       value, 16, min, max, flags | DP_F_NUM);
                break;
            case 'n':
                if (cflags == DP_C_SHORT) {
                    short int *num;
                    num = va_arg(args, short int *);
                    *num = currlen;
                } else if (cflags == DP_C_LONG) {
                    long int *num;
                    num = va_arg(args, long int *);
                    *num = (long int)currlen;
                } else if (cflags == DP_C_LLONG) {
                    LLONG *num;
                    num = va_arg(args, LLONG *);
                    *num = (LLONG) currlen;
                } else {
                    int *num;
                    num = va_arg(args, int *);
                    *num = currlen;
                }
                break;
            case '%':
                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
                break;
            case 'w':
                ch = *format++;
                break;
            default:
                break;
            }
            ch = *format++;
            state = DP_S_DEFAULT;
            flags = cflags = min = 0;
            max = -1;
            break;
        case DP_S_DONE:
            break;
        default:
            break;
        }
    }
    *truncated = (currlen > *maxlen - 1);
    if (*truncated)
        currlen = *maxlen - 1;
    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
    *retlen = currlen - 1;
    return;
}
['static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,\n                               X509_NAME *name, X509_OBJECT *ret)\n{\n    BY_DIR *ctx;\n    union {\n        struct {\n            X509 st_x509;\n            X509_CINF st_x509_cinf;\n        } x509;\n        struct {\n            X509_CRL st_crl;\n            X509_CRL_INFO st_crl_info;\n        } crl;\n    } data;\n    int ok = 0;\n    int i, j, k;\n    unsigned long h;\n    BUF_MEM *b = NULL;\n    X509_OBJECT stmp, *tmp;\n    const char *postfix = "";\n    if (name == NULL)\n        return (0);\n    stmp.type = type;\n    if (type == X509_LU_X509) {\n        data.x509.st_x509.cert_info = &data.x509.st_x509_cinf;\n        data.x509.st_x509_cinf.subject = name;\n        stmp.data.x509 = &data.x509.st_x509;\n        postfix = "";\n    } else if (type == X509_LU_CRL) {\n        data.crl.st_crl.crl = &data.crl.st_crl_info;\n        data.crl.st_crl_info.issuer = name;\n        stmp.data.crl = &data.crl.st_crl;\n        postfix = "r";\n    } else {\n        X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);\n        goto finish;\n    }\n    if ((b = BUF_MEM_new()) == NULL) {\n        X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);\n        goto finish;\n    }\n    ctx = (BY_DIR *)xl->method_data;\n    h = X509_NAME_hash(name);\n    for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {\n        BY_DIR_ENTRY *ent;\n        int idx;\n        BY_DIR_HASH htmp, *hent;\n        ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);\n        j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;\n        if (!BUF_MEM_grow(b, j)) {\n            X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);\n            goto finish;\n        }\n        if (type == X509_LU_CRL && ent->hashes) {\n            htmp.hash = h;\n            CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);\n            idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);\n            if (idx >= 0) {\n                hent = sk_BY_DIR_HASH_value(ent->hashes, idx);\n                k = hent->suffix;\n            } else {\n                hent = NULL;\n                k = 0;\n            }\n            CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);\n        } else {\n            k = 0;\n            hent = NULL;\n        }\n        for (;;) {\n            char c = \'/\';\n#ifdef OPENSSL_SYS_VMS\n            c = ent->dir[strlen(ent->dir) - 1];\n            if (c != \':\' && c != \'>\' && c != \']\') {\n                c = \':\';\n            } else {\n                c = \'\\0\';\n            }\n#endif\n            if (c == \'\\0\') {\n                BIO_snprintf(b->data, b->max,\n                             "%s%08lx.%s%d", ent->dir, h, postfix, k);\n            } else {\n                BIO_snprintf(b->data, b->max,\n                             "%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);\n            }\n#ifndef OPENSSL_NO_POSIX_IO\n# ifdef _WIN32\n#  define stat _stat\n# endif\n            {\n                struct stat st;\n                if (stat(b->data, &st) < 0)\n                    break;\n            }\n#endif\n            if (type == X509_LU_X509) {\n                if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)\n                    break;\n            } else if (type == X509_LU_CRL) {\n                if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)\n                    break;\n            }\n            k++;\n        }\n        CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);\n        j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);\n        if (j != -1)\n            tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);\n        else\n            tmp = NULL;\n        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);\n        if (type == X509_LU_CRL) {\n            CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);\n            if (!hent) {\n                htmp.hash = h;\n                idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);\n                if (idx >= 0)\n                    hent = sk_BY_DIR_HASH_value(ent->hashes, idx);\n            }\n            if (!hent) {\n                hent = OPENSSL_malloc(sizeof(*hent));\n                if (hent == NULL) {\n                    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);\n                    X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);\n                    ok = 0;\n                    goto finish;\n                }\n                hent->hash = h;\n                hent->suffix = k;\n                if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {\n                    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);\n                    OPENSSL_free(hent);\n                    ok = 0;\n                    goto finish;\n                }\n            } else if (hent->suffix < k)\n                hent->suffix = k;\n            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);\n        }\n        if (tmp != NULL) {\n            ok = 1;\n            ret->type = tmp->type;\n            memcpy(&ret->data, &tmp->data, sizeof(ret->data));\n            goto finish;\n        }\n    }\n finish:\n    BUF_MEM_free(b);\n    return (ok);\n}', 'size_t BUF_MEM_grow(BUF_MEM *str, size_t len)\n{\n    char *ret;\n    size_t n;\n    if (str->length >= len) {\n        str->length = len;\n        return (len);\n    }\n    if (str->max >= len) {\n        memset(&str->data[str->length], 0, len - str->length);\n        str->length = len;\n        return (len);\n    }\n    if (len > LIMIT_BEFORE_EXPANSION) {\n        BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);\n        return 0;\n    }\n    n = (len + 3) / 3 * 4;\n    if ((str->flags & BUF_MEM_FLAG_SECURE))\n        ret = sec_alloc_realloc(str, n);\n    else\n        ret = OPENSSL_realloc(str->data, n);\n    if (ret == NULL) {\n        BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);\n        len = 0;\n    } else {\n        str->data = ret;\n        str->max = n;\n        memset(&str->data[str->length], 0, len - str->length);\n        str->length = len;\n    }\n    return (len);\n}', 'int BIO_snprintf(char *buf, size_t n, const char *format, ...)\n{\n    va_list args;\n    int ret;\n    va_start(args, format);\n    ret = BIO_vsnprintf(buf, n, format, args);\n    va_end(args);\n    return (ret);\n}', 'int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)\n{\n    size_t retlen;\n    int truncated;\n    _dopr(&buf, NULL, &n, &retlen, &truncated, format, args);\n    if (truncated)\n        return -1;\n    else\n        return (retlen <= INT_MAX) ? (int)retlen : -1;\n}', "static void\n_dopr(char **sbuffer,\n      char **buffer,\n      size_t *maxlen,\n      size_t *retlen, int *truncated, const char *format, va_list args)\n{\n    char ch;\n    LLONG value;\n    LDOUBLE fvalue;\n    char *strvalue;\n    int min;\n    int max;\n    int state;\n    int flags;\n    int cflags;\n    size_t currlen;\n    state = DP_S_DEFAULT;\n    flags = currlen = cflags = min = 0;\n    max = -1;\n    ch = *format++;\n    while (state != DP_S_DONE) {\n        if (ch == '\\0' || (buffer == NULL && currlen >= *maxlen))\n            state = DP_S_DONE;\n        switch (state) {\n        case DP_S_DEFAULT:\n            if (ch == '%')\n                state = DP_S_FLAGS;\n            else\n                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);\n            ch = *format++;\n            break;\n        case DP_S_FLAGS:\n            switch (ch) {\n            case '-':\n                flags |= DP_F_MINUS;\n                ch = *format++;\n                break;\n            case '+':\n                flags |= DP_F_PLUS;\n                ch = *format++;\n                break;\n            case ' ':\n                flags |= DP_F_SPACE;\n                ch = *format++;\n                break;\n            case '#':\n                flags |= DP_F_NUM;\n                ch = *format++;\n                break;\n            case '0':\n                flags |= DP_F_ZERO;\n                ch = *format++;\n                break;\n            default:\n                state = DP_S_MIN;\n                break;\n            }\n            break;\n        case DP_S_MIN:\n            if (isdigit((unsigned char)ch)) {\n                min = 10 * min + char_to_int(ch);\n                ch = *format++;\n            } else if (ch == '*') {\n                min = va_arg(args, int);\n                ch = *format++;\n                state = DP_S_DOT;\n            } else\n                state = DP_S_DOT;\n            break;\n        case DP_S_DOT:\n            if (ch == '.') {\n                state = DP_S_MAX;\n                ch = *format++;\n            } else\n                state = DP_S_MOD;\n            break;\n        case DP_S_MAX:\n            if (isdigit((unsigned char)ch)) {\n                if (max < 0)\n                    max = 0;\n                max = 10 * max + char_to_int(ch);\n                ch = *format++;\n            } else if (ch == '*') {\n                max = va_arg(args, int);\n                ch = *format++;\n                state = DP_S_MOD;\n            } else\n                state = DP_S_MOD;\n            break;\n        case DP_S_MOD:\n            switch (ch) {\n            case 'h':\n                cflags = DP_C_SHORT;\n                ch = *format++;\n                break;\n            case 'l':\n                if (*format == 'l') {\n                    cflags = DP_C_LLONG;\n                    format++;\n                } else\n                    cflags = DP_C_LONG;\n                ch = *format++;\n                break;\n            case 'q':\n                cflags = DP_C_LLONG;\n                ch = *format++;\n                break;\n            case 'L':\n                cflags = DP_C_LDOUBLE;\n                ch = *format++;\n                break;\n            default:\n                break;\n            }\n            state = DP_S_CONV;\n            break;\n        case DP_S_CONV:\n            switch (ch) {\n            case 'd':\n            case 'i':\n                switch (cflags) {\n                case DP_C_SHORT:\n                    value = (short int)va_arg(args, int);\n                    break;\n                case DP_C_LONG:\n                    value = va_arg(args, long int);\n                    break;\n                case DP_C_LLONG:\n                    value = va_arg(args, LLONG);\n                    break;\n                default:\n                    value = va_arg(args, int);\n                    break;\n                }\n                fmtint(sbuffer, buffer, &currlen, maxlen,\n                       value, 10, min, max, flags);\n                break;\n            case 'X':\n                flags |= DP_F_UP;\n            case 'x':\n            case 'o':\n            case 'u':\n                flags |= DP_F_UNSIGNED;\n                switch (cflags) {\n                case DP_C_SHORT:\n                    value = (unsigned short int)va_arg(args, unsigned int);\n                    break;\n                case DP_C_LONG:\n                    value = (LLONG) va_arg(args, unsigned long int);\n                    break;\n                case DP_C_LLONG:\n                    value = va_arg(args, unsigned LLONG);\n                    break;\n                default:\n                    value = (LLONG) va_arg(args, unsigned int);\n                    break;\n                }\n                fmtint(sbuffer, buffer, &currlen, maxlen, value,\n                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),\n                       min, max, flags);\n                break;\n            case 'f':\n                if (cflags == DP_C_LDOUBLE)\n                    fvalue = va_arg(args, LDOUBLE);\n                else\n                    fvalue = va_arg(args, double);\n                fmtfp(sbuffer, buffer, &currlen, maxlen,\n                      fvalue, min, max, flags);\n                break;\n            case 'E':\n                flags |= DP_F_UP;\n            case 'e':\n                if (cflags == DP_C_LDOUBLE)\n                    fvalue = va_arg(args, LDOUBLE);\n                else\n                    fvalue = va_arg(args, double);\n                break;\n            case 'G':\n                flags |= DP_F_UP;\n            case 'g':\n                if (cflags == DP_C_LDOUBLE)\n                    fvalue = va_arg(args, LDOUBLE);\n                else\n                    fvalue = va_arg(args, double);\n                break;\n            case 'c':\n                doapr_outch(sbuffer, buffer, &currlen, maxlen,\n                            va_arg(args, int));\n                break;\n            case 's':\n                strvalue = va_arg(args, char *);\n                if (max < 0) {\n                    if (buffer)\n                        max = INT_MAX;\n                    else\n                        max = *maxlen;\n                }\n                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,\n                       flags, min, max);\n                break;\n            case 'p':\n                value = (long)va_arg(args, void *);\n                fmtint(sbuffer, buffer, &currlen, maxlen,\n                       value, 16, min, max, flags | DP_F_NUM);\n                break;\n            case 'n':\n                if (cflags == DP_C_SHORT) {\n                    short int *num;\n                    num = va_arg(args, short int *);\n                    *num = currlen;\n                } else if (cflags == DP_C_LONG) {\n                    long int *num;\n                    num = va_arg(args, long int *);\n                    *num = (long int)currlen;\n                } else if (cflags == DP_C_LLONG) {\n                    LLONG *num;\n                    num = va_arg(args, LLONG *);\n                    *num = (LLONG) currlen;\n                } else {\n                    int *num;\n                    num = va_arg(args, int *);\n                    *num = currlen;\n                }\n                break;\n            case '%':\n                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);\n                break;\n            case 'w':\n                ch = *format++;\n                break;\n            default:\n                break;\n            }\n            ch = *format++;\n            state = DP_S_DEFAULT;\n            flags = cflags = min = 0;\n            max = -1;\n            break;\n        case DP_S_DONE:\n            break;\n        default:\n            break;\n        }\n    }\n    *truncated = (currlen > *maxlen - 1);\n    if (*truncated)\n        currlen = *maxlen - 1;\n    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\\0');\n    *retlen = currlen - 1;\n    return;\n}"]