Path: blob/main/contrib/libfido2/openbsd-compat/bsd-asprintf.c
39492 views
/*1* Copyright (c) 2004 Darren Tucker.2*3* Based originally on asprintf.c from OpenBSD:4* Copyright (c) 1997 Todd C. Miller <[email protected]>5*6* Permission to use, copy, modify, and distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/1819#include "openbsd-compat.h"2021#ifndef HAVE_ASPRINTF2223#include <errno.h>24#include <limits.h> /* for INT_MAX */25#include <stdarg.h>26#include <stdio.h> /* for vsnprintf */27#include <stdlib.h>2829#define VA_COPY(dest, src) va_copy(dest, src)3031#define INIT_SZ 1283233int34vasprintf(char **str, const char *fmt, va_list ap)35{36int ret;37va_list ap2;38char *string, *newstr;39size_t len;4041if ((string = malloc(INIT_SZ)) == NULL)42goto fail;4344VA_COPY(ap2, ap);45ret = vsnprintf(string, INIT_SZ, fmt, ap2);46va_end(ap2);47if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */48*str = string;49} else if (ret == INT_MAX || ret < 0) { /* Bad length */50free(string);51goto fail;52} else { /* bigger than initial, realloc allowing for nul */53len = (size_t)ret + 1;54if ((newstr = realloc(string, len)) == NULL) {55free(string);56goto fail;57}58VA_COPY(ap2, ap);59ret = vsnprintf(newstr, len, fmt, ap2);60va_end(ap2);61if (ret < 0 || (size_t)ret >= len) { /* failed with realloc'ed string */62free(newstr);63goto fail;64}65*str = newstr;66}67return (ret);6869fail:70*str = NULL;71errno = ENOMEM;72return (-1);73}7475int asprintf(char **str, const char *fmt, ...)76{77va_list ap;78int ret;7980*str = NULL;81va_start(ap, fmt);82ret = vasprintf(str, fmt, ap);83va_end(ap);8485return ret;86}87#endif888990