{"id":15049248,"url":"https://github.com/neved4/asprintf","last_synced_at":"2025-08-31T16:43:13.173Z","repository":{"id":214404062,"uuid":"736064097","full_name":"Neved4/asprintf","owner":"Neved4","description":"🛠️ One true asprintf, vasprintf!","archived":false,"fork":false,"pushed_at":"2025-03-21T23:49:54.000Z","size":42,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-09T15:22:16.836Z","etag":null,"topics":["asprintf","c","c99","clang","clib","clibs","gcc","gnu","header","iso","lib","libc","misra","misra-c","musl-libc","portable","posix","stdlib","unit-testing","vasprintf"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Neved4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-26T22:14:20.000Z","updated_at":"2025-03-21T23:49:57.000Z","dependencies_parsed_at":"2023-12-28T00:58:15.501Z","dependency_job_id":"62b3fa2b-cb4b-4253-b98b-af0ef021bb76","html_url":"https://github.com/Neved4/asprintf","commit_stats":null,"previous_names":["neved4/asprintf"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Neved4/asprintf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neved4%2Fasprintf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neved4%2Fasprintf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neved4%2Fasprintf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neved4%2Fasprintf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Neved4","download_url":"https://codeload.github.com/Neved4/asprintf/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neved4%2Fasprintf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273010949,"owners_count":25030368,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-31T02:00:09.071Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asprintf","c","c99","clang","clib","clibs","gcc","gnu","header","iso","lib","libc","misra","misra-c","musl-libc","portable","posix","stdlib","unit-testing","vasprintf"],"created_at":"2024-09-24T21:19:16.096Z","updated_at":"2025-08-31T16:43:13.154Z","avatar_url":"https://github.com/Neved4.png","language":"C","readme":"[![C](https://img.shields.io/badge/ISO_C99-A8B9CC?logo=c\u0026logoColor=fff)][C99]\n[![IEEE](https://img.shields.io/badge/POSIX.1\u0026#8209;2024-00629B?logo=ieee\u0026logoColor=fff)][POSIX.1-2024]\n[![CodeQL](https://github.com/github/docs/actions/workflows/codeql.yml/badge.svg)](https://github.com/Neved4/twc/actions/workflows/codeql.yml)\n[![clib](https://img.shields.io/badge/clib-pkg-2AAB47?logo=github\u0026logoColor=959DA5\u0026labelColor=2B3137)](https://github.com/Neved4/homebrew-tap/blob/main/Formula/gotwc.rb)\n\n# `asprintf` - One True `asprintf`, `vasprintf`! 🛠️\n\nRobust, portable implementation of `asprintf()`, `vasprintf()`.\nThoroughly tested.\n\n## Highlights\n\n- 🚀 _**Fast**_ - performance akin other implementations\n- 📦 _**Simple**_ - zero dependencies, lightweight\n  (`37 lines`, `566 bytes`) and ISO [C99] compatible.\n- 🔒 _**Robust**_ - safety-first, with substantial [unit testing](test.c).\n- ⚙️ _**Compatible**_ - interop across different systems, drop-in `asprintf`, `vasprintf` replacement for [glibc], [*BSD libc][OpenBSD `asprintf`],\n  [musl libc] and [many more](#see-also).\n\n## Motivation\n\nWanted to have a version of `asprintf` that is simple, robust and just works\neverywhere. Needed it to be backward-compatible with existing `libc` libraries,\nconsistent across diverse platforms and systems. It should also focus on\ncorrectness, minimize unexpected behavior, be thoroughly tested, be easy to read\nand stick to both [C99] and [POSIX.1-2024].\n\nThis process also gave me the opportunity to review existing implementations and\ndeepen my understanding of pointers and systems programming.\n\n## Getting Started\n\n\u003e [!IMPORTANT]\n\u003e Both `asprintf()` and `vasprintf()` are now included in\n\u003e [POSIX.1-2024][posix-2024-announced], see [Austin Group Bug\n\u003e #1496](https://www.austingroupbugs.net/view.php?id=1496). You can check the\n\u003e current specification [here][posix-asprintf]. For systems supporting\n\u003e `POSIX.1-2024` or later, `Neved4/asprintf` is no longer necessary. For systems\n\u003e limited to `POSIX.1-2017` or under, it offers a practical solution.\n\n### Prerequisites\n\nIf you are building [`asprintf`][Neved4/asprintf], ensure you have:\n\n- A [C] compiler that supports [C99]\n\n### Installing\n\nIf you have [clib] installed, run:\n```console\n$ clib install Neved4/asprintf\n```\n\nIf you don't have the above, start by cloning the repository:\n```console\n$ git clone https://github.com/Neved4/asprintf\n```\n\nOnce you've cloned the repository, build by executing:\n```console\n$ make asprintf\n```\n\nAlternatively, if you have [`zig`]:\n```console\n$ zig cc asprintf.c -t asprintf\n```\n\n### Usage\n\n```c\n// asprintf, vasprintf - print to allocated string\n\n#include \"asprintf.h\"\n\nint asprintf(char **strp, const char *fmt, ...);\n\nint vasprintf(char **strp, const char *fmt, va_list ap);\n```\n\n### Examples\n\nConsider a `getconf()` function to retrieve a `config` specified path, that\nsupports both `XDG_CONFIG_HOME` and fallbacks:\n\n```c\nchar *getconf() {\n    const char *file = \"tz.conf\", *home = getenv(\"HOME\"),\n        *xdg_config_home = getenv(\"XDG_CONFIG_HOME\");\n    char *config = NULL;\n\n    // Path building logic\n\n    return config;\n}\n```\n\nAfter which we'll have to lay down our path building logic.\n\n###### Before `asprintf`\n\n```c\nif (access(\"tz.conf\", F_OK) != -1) {\n    config = strdup(\"tz.conf\");\n} else if (xdg_config_home) {\n    size_t len = strlen(xdg_config_home) + strlen(\"twc\") + strlen(file) + 3;\n    config = (char *)malloc(len);\n    if (config != NULL) {\n        snprintf(config, len, \"%s/%s/%s\", xdg_config_home, \"twc\", file);\n    }\n} else if (home) {\n    size_t len = strlen(home) + strlen(\".config/twc\") + strlen(file) + 3;\n    config = (char *)malloc(len);\n    if (config != NULL) {\n        snprintf(config, len, \"%s/%s/%s\", home, \".config/twc\", file);\n    }\n}\n```\n\n###### After `asprintf`\n\n```c\nif (access(\"tz.conf\", F_OK) != -1) {\n    config = strdup(\"tz.conf\");\n} else if (xdg_config_home) {\n    asprintf(\u0026config, \"%s/%s/%s\", xdg_config_home, \"twc\", file);\n} else if (home) {\n    asprintf(\u0026config, \"%s/%s/%s\", home, \".config/twc\", file);\n}\n```\n\n### Testing\n\nTo run all the tests against `asprintf` execute the following command:\n```sh\ncc test.c asprintf.c -o test \u0026\u0026 ./test\n```\n\nTo use your system's default `asprintf(3)`, run this instead:\n```sh\ncc test.c -o test \u0026\u0026 ./test\n```\n\nTo link it against other `asprintf` implementations, run:\n```sh\ncc test.c /path/to/asprintf.c -o test \u0026\u0026 ./test\n```\n\nAny of the above will output something like:\n```rust\n Ok \"Memory allocation\"\n Ok \"Empty string as input\"\n Ok \"String formatting variations\"\n Ok \"Special characters in format string\"\nErr \"Boundary cases for integers\"\n\n// More tests\n\n-----------\nPassing: 4\n Failed: 1\n  Total: 5\n```\n\n### Docker\n\nTo compile the binary inside a [Docker] image, run:\n```sh\ndocker build .\n```\n\n## Compatibility\n\nRuns on _**Linux**_, _**macOS**_ and _**\\*BSD**_ systems on both [`x86_64`]\nand [`arm64`]. Builds with [`clang`], [`gcc`], [`tcc`], [`zig`] and any\nother compiler that supports [C99] or later.\n\nShould be compatible with [glibc], [GLib], FreeBSD libc, musl libc `asprintf`.\n\n## Standards\n\n`asprintf` is compatible with both [POSIX.1-2024],[^1] and [C99].[^2]\n\n## License\n\n`asprintf` is licensed under the terms of the [MIT License].\n\nSee the [LICENSE](LICENSE) file for details.\n\n## See Also\n\n#### Reference\n\n- [ISO/IEC 9899][C99]\n- [ISO/IEC DIS 9945][POSIX.1-2024]\n- [ISO/IEC TS 17961:2013](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1579.pdf)\n- [MISRA C:2012](https://electrovolt.ir/wp-content/uploads/2022/09/MISRA-C_2012_-Guidelines-for-the-Use-of-the-C-Language-in-Critical-Systems-Motor-Industry-Research-Association-2013-2013.pdf)\n- [SEI CERT C](https://wiki.sei.cmu.edu/confluence/display/c) ([PDF](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-c-coding-standard-2016-v01.pdf))\n\n#### System implementations\n\n|               Source | Docs                           |\n| -------------------: | ------------------------------ |\n|  [Debian `asprintf`] | [manpages.debian.org/asprintf] |\n| [FreeBSD `asprintf`] | [man.freebsd.org/asprintf]     |\n| [OpenBSD `asprintf`] | [man.openbsd.org/asprintf]     |\n|  [NetBSD `asprintf`] | [man.netbsd.org/asprintf.3]    |\n|   Solaris `asprintf` | [docs.oracle.com/asprintf-3c]  |\n|      z/OS `asprintf` | [ibm.com/docs/zos/asprintf]    |\n|  [sortix `asprintf`] |                                |\n\n#### Other `libc` implementations\n\n- [cosmopolitan/asprintf.c](https://github.com/jart/cosmopolitan/blob/master/libc/stdio/asprintf.c)\n- [dietlibc](https://www.fefe.de/dietlibc/)\n- [glibc/asprintf.c](https://sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/asprintf.c;h=bb8f4bffc19292c7173d8180b4c2428411d5c269;hb=HEAD)\n- [musl/asprintf.c](https://git.musl-libc.org/cgit/musl/tree/src/stdio/asprintf.c)\n- [newlib/asprintf.c](https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdio/asprintf.c;hb=HEAD)\n- [picolibc/asprintf.c](https://github.com/picolibc/picolibc/blob/main/newlib/libc/tinystdio/asprintf.c#L42)\n- [uclibc/asprintf.c](https://gogs.waldemar-brodkorb.de/oss/uclibc-ng/src/master/libc/stdio/asprintf.c)\n\n#### Other `asprintf` implementations\n\n- [gcc/libiberty/asprintf.c](https://github.com/gcc-mirror/gcc/blob/master/libiberty/asprintf.c#L47)\n- [akharrou/ft_asprintf](https://github.com/akharrou/42-Project-Ft_Printf/blob/master/ft_asprintf.c)\n- [andrelmbackman/ft_printf](https://github.com/andrelmbackman/ft_printf)\n- [d4wae89d498/ft_asprintf](https://github.com/d4wae89d498/libftprintf/blob/master/ft_asprintf.c)\n- [dragonblocks/asprintf](https://github.com/dragonblocks/asprintf/blob/main/asprintf.c)\n- [eiszapfen2000/asprintf](https://github.com/eiszapfen2000/asprintf/blob/master/asprintf.c)\n- [finwo/c-asprintf](https://github.com/finwo/c-asprintf/blob/main/src/asprintf.c)\n- [jkaivo/asprintf](https://github.com/jkaivo/asprintf/blob/asprintf/asprintf.h)\n- [jwerle/asprintf.c](https://github.com/jwerle/asprintf.c/blob/master/asprintf.c)\n- [libressl/portable](https://github.com/libressl/portable/blob/master/crypto/compat/bsd-asprintf.c#L84)\n- [lordmulder/asprintf-msvc](https://github.com/lordmulder/asprintf-msvc/blob/master/asprintf_msvc.c#L35)\n- [n-nino/vc6-asprintf](https://github.com/n-nino/vc6-asprintf/blob/master/asprintf.c)\n- [naev/naev/asprintf](https://github.com/naev/naev/blob/main/utils/model-view-c/nstr.c)\n- [tap3edit/mp/mpasprintf](https://github.com/tap3edit/mp/blob/master/src/mp.c#L705)\n- [timbaker/asprintf](https://github.com/timbaker/asprintf/blob/master/asprintf.c)\n- [weiss/c99-snprintf](https://github.com/weiss/c99-snprintf/blob/master/snprintf.c#L1528)\n\n#### Further reading\n\n- [Chris Wellons: How to Write Portable C Without Complicating Your Build](https://nullprogram.com/blog/2017/03/30/)\n- [Fedora Defensive Coding Guide: The C Programming Language](https://docs.fedoraproject.org/en-US/defensive-coding/programming-languages/C/#sect-Defensive_Coding-C-Libc)\n- [FreeBSD Developers' Handbook: Chapter 3. Secure Programming](https://docs.freebsd.org/en/books/developers-handbook/secure/)\n- [GNU Autoconf: Portability of C Functions](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.71/autoconf.html#Function-Portability)\n- [GNU Autoconf: Portable C and C++ Programming](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.71/autoconf.html#Portable-C-and-C_002b_002b)\n- [Oracle Developer's Guide to Solaris: Security Considerations When Using C Functions](https://docs.oracle.com/cd/E36784_01/html/E36855/gnclc.html)\n\n[`arm64`]: https://en.wikipedia.org/wiki/AArch64\n[`x86_64`]: https://en.wikipedia.org/wiki/X86-64\n[`clang`]: https://clang.llvm.org/\n[`gcc`]: https://gcc.gnu.org/\n[`tcc`]: https://bellard.org/tcc/\n[`zig`]: https://ziglang.org/\n[Neved4/asprintf]: https://github.com/Neved4/asprintf\n[C]: https://en.wikipedia.org/wiki/C_(programming_language)\n[C99]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf\n[POSIX.1-2024]: https://pubs.opengroup.org/onlinepubs/9799919799/\n[posix-asprintf]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/asprintf.html\n[posix-2024-announced]: https://ieeexplore.ieee.org/document/10555529\n[MIT License]: https://opensource.org/license/mit/\n[clib]: https://github.com/clibs/clib\n[Docker]: https://www.docker.com/\n[GLib]: https://docs.gtk.org/glib/index.html\n[glibc]: https://www.gnu.org/software/libc/\n[musl libc]: https://musl.libc.org/\n\n[Debian `asprintf`]: https://sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/asprintf.c;h=bb8f4bffc19292c7173d8180b4c2428411d5c269;hb=HEAD\n[FreeBSD `asprintf`]: https://github.com/lattera/freebsd/blob/master/lib/libc/stdio/asprintf.c#L46\n[OpenBSD `asprintf`]: https://github.com/openbsd/src/blob/434871b630fbbd06e39f45c13bc9e199cfd986ee/lib/libc/stdio/asprintf.c#L30\n[NetBSD `asprintf`]: https://github.com/IIJ-NetBSD/netbsd-src/blob/master/lib/libc/stdio/vasprintf.c\n[sortix `asprintf`]: https://gitlab.com/sortix/sortix/-/commit/2fe13d33c9e1da46aa444367f16680cafa3a63a3\n\u003c!-- [Solaris `asprintf`]: --\u003e\n\u003c!-- [z/OS `asprintf`]: --\u003e\n\n[manpages.debian.org/asprintf]: https://manpages.debian.org/unstable/manpages-dev/asprintf.3.en.html\n[man.freebsd.org/asprintf]: https://man.freebsd.org/cgi/man.cgi?query=asprintf\n[man.openbsd.org/asprintf]: https://man.openbsd.org/asprintf\n[man.netbsd.org/asprintf.3]: https://man.netbsd.org/asprintf.3\n[docs.oracle.com/asprintf-3c]: https://docs.oracle.com/cd/E88353_01/html/E37843/asprintf-3c.html\n[ibm.com/docs/zos/asprintf]: https://www.ibm.com/docs/en/zos/3.1.0?topic=functions-asprintf-vasprintf-print-allocated-string\n\n[^1]: _IEEE Std 1003.1-2024: Standard for Information Technology\n    — Portable Operating System Interface (POSIX®)_, \\\n    ISO/IEC DIS 9945. URL: https://pubs.opengroup.org/onlinepubs/9799919799/\n[^2]: _ISO/IEC 9899: Standard for Information Technology\n    — Programming languages — C_, ISO/IEC 9899:2023. \\\n    URL: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneved4%2Fasprintf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneved4%2Fasprintf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneved4%2Fasprintf/lists"}