shithub: mc

Download patch

ref: 2c0fbf27314d04cb3bb5ab1ea3f9b7bae556f89a
parent: 4e656a4f039b9230c820f12d3b1e4a5c8e55cf47
author: Ori Bernstein <[email protected]>
date: Fri Jul 24 17:19:50 EDT 2015

Replace snprintf with a variant that asserts when out of buffer.

    Let's not happy silent truncate.

--- a/6/gen.c
+++ b/6/gen.c
@@ -55,15 +55,15 @@
 char *genlocallblstr(char *buf, size_t sz)
 {
     if (asmsyntax == Plan9)
-        snprintf(buf, 128, ".L%d<>", nextlbl++);
+        bprintf(buf, 128, ".L%d<>", nextlbl++);
     else
-        snprintf(buf, 128, ".L%d", nextlbl++);
+        bprintf(buf, 128, ".L%d", nextlbl++);
     return buf;
 }
 
 char *genlblstr(char *buf, size_t sz)
 {
-    snprintf(buf, 128, ".L%d", nextlbl++);
+    bprintf(buf, 128, ".L%d", nextlbl++);
     return buf;
 }
 
@@ -96,7 +96,7 @@
     if (name[0] == '.')
         pf = "";
 
-    snprintf(buf, sizeof buf, "%s%s%s%s%s", pf, ns, sep, name, vis);
+    bprintf(buf, sizeof buf, "%s%s%s%s%s", pf, ns, sep, name, vis);
     return strdup(buf);
 }
 
@@ -112,15 +112,15 @@
             sep = "$";
         }
         if (ty->vis == Visexport || ty->isimport)
-            snprintf(buf, bufsz, "_tydesc$%s%s%s", ns, sep, ty->name->name.name);
+            bprintf(buf, bufsz, "_tydesc$%s%s%s", ns, sep, ty->name->name.name);
         else
-            snprintf(buf, bufsz, "_tydesc$%s%s%s$%d", ns, sep, ty->name->name.name, ty->tid);
+            bprintf(buf, bufsz, "_tydesc$%s%s%s$%d", ns, sep, ty->name->name.name, ty->tid);
     } else {
         if (file->file.globls->name) {
             ns = file->file.globls->name;
             sep = "$";
         }
-        snprintf(buf, bufsz, "_tydesc%s%s$%d",sep, ns, ty->tid);
+        bprintf(buf, bufsz, "_tydesc%s%s$%d",sep, ns, ty->tid);
     }
     return buf;
 }
--- a/6/genp9.c
+++ b/6/genp9.c
@@ -388,10 +388,10 @@
         return;
     if (b->isglobl) {
         fprintf(fd, "GLOBL %s%s+0(SB),$%zd\n", Symprefix, b->lbl, blobsz(b));
-        snprintf(lbl, sizeof lbl, "%s%s", Symprefix, b->lbl);
+        bprintf(lbl, sizeof lbl, "%s%s", Symprefix, b->lbl);
     } else {
         fprintf(fd, "GLOBL %s%s<>+0(SB),$%zd\n", Symprefix, b->lbl, blobsz(b));
-        snprintf(lbl, sizeof lbl, "%s%s<>", Symprefix, b->lbl);
+        bprintf(lbl, sizeof lbl, "%s%s<>", Symprefix, b->lbl);
     }
     writeblob(fd, b, 0, lbl);
 }
--- a/6/isel.c
+++ b/6/isel.c
@@ -938,7 +938,7 @@
         for (i = 0; i < bb->nnl; i++) {
             /* put in a comment that says where this line comes from */
             n = bb->nl[i];
-            snprintf(buf, sizeof buf, "bb = %ld, bbidx = %ld, %s:%d",
+            bprintf(buf, sizeof buf, "bb = %ld, bbidx = %ld, %s:%d",
                      j, i, file->file.files[n->loc.file], n->loc.line);
             g(is, Icomment, locstrlbl(buf), NULL);
             isel(is, fn->cfg->bb[j]->nl[i]);
--- a/6/main.c
+++ b/6/main.c
@@ -56,7 +56,7 @@
     if (psuffix != NULL)
         swapsuffix(buf, sz, outfile, psuffix, suf);
     else
-        snprintf(buf, sz, "%s%s", outfile, suf);
+        bprintf(buf, sz, "%s%s", outfile, suf);
 }
 
 static void assemble(char *asmsrc, char *path)
@@ -113,7 +113,7 @@
     else
         base = path;
     gettimeofday(&tv, NULL);
-    snprintf(buf, bufsz, "%s/tmp%lx%lx-%s%s", tmpdir, (long)tv.tv_sec, (long)tv.tv_usec, base, suffix);
+    bprintf(buf, bufsz, "%s/tmp%lx%lx-%s%s", tmpdir, (long)tv.tv_sec, (long)tv.tv_usec, base, suffix);
     return buf;
 }
 
--- a/6/simp.c
+++ b/6/simp.c
@@ -301,7 +301,7 @@
     static int nexttmp;
     Node *t, *r, *n;
 
-    snprintf(buf, 128, ".t%d", nexttmp++);
+    bprintf(buf, 128, ".t%d", nexttmp++);
     n = mkname(e->loc, buf);
     t = mkdecl(e->loc, n, ty);
     r = mkexpr(e->loc, Ovar, n, NULL);
--- a/6/typeinfo.c
+++ b/6/typeinfo.c
@@ -60,11 +60,11 @@
     if (n->name.ns) {
         len = strlen(n->name.name) + strlen(n->name.ns) + 1;
         buf = xalloc(len + 1);
-        snprintf(buf, len + 1, "%s.%s", n->name.ns, n->name.name);
+        bprintf(buf, len + 1, "%s.%s", n->name.ns, n->name.name);
     } else {
         len = strlen(n->name.name);
         buf = xalloc(len + 1);
-        snprintf(buf, len + 1, "%s", n->name.name);
+        bprintf(buf, len + 1, "%s", n->name.name);
     }
     lappend(sub, nsub, mkblobi(Btimin, len));
     lappend(sub, nsub, mkblobbytes(buf, len));
@@ -175,7 +175,7 @@
                 unionmemb(&sub, &nsub, ty->udecls[i]);
             break;
         case Tyname:
-            i = snprintf(buf, sizeof buf, "%s", Symprefix);
+            i = bprintf(buf, sizeof buf, "%s", Symprefix);
             tydescid(buf + i, sizeof buf - i, ty);
             lappend(&sub, &nsub, mkblobref(buf, 0, ty->isimport || ty->vis == Visexport));
             break;
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -218,7 +218,7 @@
         }
     }
     post = mkbb(cfg);
-    snprintf(buf, sizeof buf, ".R%d", nextret++);
+    bprintf(buf, sizeof buf, ".R%d", nextret++);
     label(cfg, mklbl(fn->loc, buf), post);
 
     cfg->start = pre;
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -934,7 +934,7 @@
     char name[1024];
     char *p;
 
-    snprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
+    bprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
     p = name;
     while (*p) {
         if (!isalnum(*p) && *p != '_')
@@ -964,7 +964,7 @@
     static int nextpseudoid;
     char buf[128];
 
-    snprintf(buf, 128, ".pdecl%d", nextpseudoid++);
+    bprintf(buf, 128, ".pdecl%d", nextpseudoid++);
     return mkdecl(l, mkname(l, buf), t);
 }
 
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -73,9 +73,9 @@
     sep = "";
 
     if (exprop(args[0]) == Ovar)
-        p += snprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
+        p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
     else
-        p += snprintf(p, end - p, "<e>(");
+        p += bprintf(p, end - p, "<e>(");
     for (i = 1; i < nargs; i++) {
         et = tyfix(st, NULL, exprtype(args[i]), 1);
         if (et != NULL)
@@ -84,14 +84,14 @@
             t = strdup("?");
 
         if (exprop(args[i]) == Ovar)
-            p += snprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
+            p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
         else
-            p += snprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
+            p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
         sep = ", ";
         free(t);
     }
     t = tystr(tyfix(st, NULL, exprtype(args[0])->sub[0], 1));
-    p += snprintf(p, end - p, "): %s", t);
+    p += bprintf(p, end - p, "): %s", t);
     free(t);
 }
 
@@ -128,7 +128,7 @@
         case Ndecl:
             d = declname(n);
             t = nodetystr(st, n);
-            snprintf(buf, sizeof buf, "%s:%s", d, t);
+            bprintf(buf, sizeof buf, "%s:%s", d, t);
             s = strdup(buf);
             free(t);
             break;
@@ -154,21 +154,21 @@
                 t3 = nodetystr(st, args[2]);
             switch (opclass[exprop(n)]) {
                 case OTbin:
-                    snprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
+                    bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
                     break;
                 case OTpre:
-                    snprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]);
+                    bprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]);
                     break;
                 case OTpost:
-                    snprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]);
+                    bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]);
                     break;
                 case OTzarg:
-                    snprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]);
+                    bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]);
                     break;
                 case OTmisc:
                     switch (exprop(n)) {
                         case Ovar:
-                            snprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t);
+                            bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t);
                             break;
                         case Ocall:
                             ctxstrcall(buf, sizeof buf, st, n);
@@ -175,26 +175,26 @@
                             break;
                         case Oidx:
                             if (exprop(args[0]) == Ovar)
-                                snprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
+                                bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
                             else
-                                snprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
+                                bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
                             break;
                         case Oslice:
                             if (exprop(args[0]) == Ovar)
-                                snprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
+                                bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
                             else
-                                snprintf(buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
+                                bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
                             break;
                         case Omemb:
-                            snprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
+                            bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
                             break;
                         default:
-                            snprintf(buf, sizeof buf, "%s:%s", d, t);
+                            bprintf(buf, sizeof buf, "%s:%s", d, t);
                             break;
                     }
                     break;
                 default:
-		    snprintf(buf, sizeof buf, "%s", d);
+		    bprintf(buf, sizeof buf, "%s", d);
                     break;
             }
             free(t);
@@ -721,7 +721,7 @@
         n = 0;
         for (i = 0; bsiter(a->traits, &i); i++) {
             if (!b->traits || !bshas(b->traits, i))
-                n += snprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep, namestr(traittab[i]->name));
+                n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep, namestr(traittab[i]->name));
             sep = ",";
         }
         tyfmt(abuf, sizeof abuf, a);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -463,6 +463,7 @@
 char *strdupn(char *s, size_t len);
 char *strjoin(char *u, char *v);
 void *memdup(void *mem, size_t len);
+size_t bprintf(char *buf, size_t len, char *fmt, ...);
 
 /* parsing etc */
 void tokinit(char *file);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -370,8 +370,8 @@
         return n->decl.name;
     p = buf;
     end = buf + sizeof buf;
-    p += snprintf(p, end - p, "%s", n->decl.name->name.name);
-    p += snprintf(p, end - p, "$");
+    p += bprintf(p, end - p, "%s", n->decl.name->name.name);
+    p += bprintf(p, end - p, "$");
     p += tyidfmt(p, end - p, t);
     name = mkname(n->loc, buf);
     if (n->decl.name->name.ns)
--- a/parse/type.c
+++ b/parse/type.c
@@ -409,8 +409,8 @@
     p = buf;
     end = p + len;
     if (n->name.ns)
-        p += snprintf(p, end - p, "%s.", n->name.ns);
-    p += snprintf(p, end - p, "%s", n->name.name);
+        p += bprintf(p, end - p, "%s.", n->name.ns);
+    p += bprintf(p, end - p, "%s", n->name.name);
     return len - (end - p);
 }
 
@@ -440,11 +440,11 @@
     p = buf;
     end = p + len;
 
-    p += snprintf(p, end - p, " :: ");
+    p += bprintf(p, end - p, " :: ");
     sep = "";
     for (i = 0; i < ntraittab; i++) {
         if (bshas(t->traits, i)) {
-            p += snprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
+            p += bprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
             sep = ",";
         }
     }
@@ -459,14 +459,14 @@
 
     p = buf;
     end = p + len;
-    p += snprintf(p, end - p, "struct\n");
+    p += bprintf(p, end - p, "struct\n");
     for (i = 0; i < t->nmemb; i++) {
         name = declname(t->sdecls[i]);
         ty = tystr(decltype(t->sdecls[i]));
-        p += snprintf(p, end - p, "\t%s:%s\n ", name, ty);
+        p += bprintf(p, end - p, "\t%s:%s\n ", name, ty);
         free(ty);
     }
-    p += snprintf(p, end - p, ";;");
+    p += bprintf(p, end - p, ";;");
     return p - buf;
 }
 
@@ -478,18 +478,18 @@
 
     p = buf;
     end = p + len;
-    p += snprintf(p, end - p, "union\n");
+    p += bprintf(p, end - p, "union\n");
     for (i = 0; i < t->nmemb; i++) {
         name = namestr(t->udecls[i]->name);
         if (t->udecls[i]->etype) {
             ty = tystr(t->udecls[i]->etype);
-            p += snprintf(p, end - p, "\t`%s %s\n", name, ty);
+            p += bprintf(p, end - p, "\t`%s %s\n", name, ty);
             free(ty);
         } else {
-            p += snprintf(p, end - p, "\t`%s\n", name);
+            p += bprintf(p, end - p, "\t`%s\n", name);
         }
     }
-    p += snprintf(p, end - p, ";;");
+    p += bprintf(p, end - p, ";;");
     return p - buf;
 }
 
@@ -501,13 +501,13 @@
     sep = "";
     p = buf;
     end = p + len;
-    p += snprintf(p, end - p, "(");
+    p += bprintf(p, end - p, "(");
     for (i = 0; i < narg; i++)  {
-        p += snprintf(p, end - p, "%s", sep);
+        p += bprintf(p, end - p, "%s", sep);
         p += tybfmt(p, end - p, arg[i]);
         sep = ", ";
     }
-    p += snprintf(p, end - p, ")");
+    p += bprintf(p, end - p, ")");
     return p - buf;
 }
 
@@ -522,82 +522,82 @@
     p = buf;
     end = p + len;
     if (!t) {
-        p += snprintf(p, end - p, "tynil");
+        p += bprintf(p, end - p, "tynil");
         return len - (end - p);
     }
     switch (t->type) {
-        case Tybad:     p += snprintf(p, end - p, "BAD");       break;
-        case Tyvoid:    p += snprintf(p, end - p, "void");      break;
-        case Tybool:    p += snprintf(p, end - p, "bool");      break;
-        case Tychar:    p += snprintf(p, end - p, "char");      break;
-        case Tyint8:    p += snprintf(p, end - p, "int8");      break;
-        case Tyint16:   p += snprintf(p, end - p, "int16");     break;
-        case Tyint:     p += snprintf(p, end - p, "int");       break;
-        case Tyint32:   p += snprintf(p, end - p, "int32");     break;
-        case Tyint64:   p += snprintf(p, end - p, "int64");     break;
-        case Tylong:    p += snprintf(p, end - p, "long");      break;
-        case Tybyte:    p += snprintf(p, end - p, "byte");      break;
-        case Tyuint8:   p += snprintf(p, end - p, "uint8");     break;
-        case Tyuint16:  p += snprintf(p, end - p, "uint16");    break;
-        case Tyuint:    p += snprintf(p, end - p, "uint");      break;
-        case Tyuint32:  p += snprintf(p, end - p, "uint32");    break;
-        case Tyuint64:  p += snprintf(p, end - p, "uint64");    break;
-        case Tyulong:   p += snprintf(p, end - p, "ulong");     break;
-        case Tyflt32: p += snprintf(p, end - p, "flt32");   break;
-        case Tyflt64: p += snprintf(p, end - p, "flt64");   break;
-        case Tyvalist:  p += snprintf(p, end - p, "...");       break;
+        case Tybad:     p += bprintf(p, end - p, "BAD");       break;
+        case Tyvoid:    p += bprintf(p, end - p, "void");      break;
+        case Tybool:    p += bprintf(p, end - p, "bool");      break;
+        case Tychar:    p += bprintf(p, end - p, "char");      break;
+        case Tyint8:    p += bprintf(p, end - p, "int8");      break;
+        case Tyint16:   p += bprintf(p, end - p, "int16");     break;
+        case Tyint:     p += bprintf(p, end - p, "int");       break;
+        case Tyint32:   p += bprintf(p, end - p, "int32");     break;
+        case Tyint64:   p += bprintf(p, end - p, "int64");     break;
+        case Tylong:    p += bprintf(p, end - p, "long");      break;
+        case Tybyte:    p += bprintf(p, end - p, "byte");      break;
+        case Tyuint8:   p += bprintf(p, end - p, "uint8");     break;
+        case Tyuint16:  p += bprintf(p, end - p, "uint16");    break;
+        case Tyuint:    p += bprintf(p, end - p, "uint");      break;
+        case Tyuint32:  p += bprintf(p, end - p, "uint32");    break;
+        case Tyuint64:  p += bprintf(p, end - p, "uint64");    break;
+        case Tyulong:   p += bprintf(p, end - p, "ulong");     break;
+        case Tyflt32: p += bprintf(p, end - p, "flt32");   break;
+        case Tyflt64: p += bprintf(p, end - p, "flt64");   break;
+        case Tyvalist:  p += bprintf(p, end - p, "...");       break;
 
         case Typtr:     
             p += tybfmt(p, end - p, t->sub[0]);
-            p += snprintf(p, end - p, "#");
+            p += bprintf(p, end - p, "#");
             break;
         case Tyslice:
             p += tybfmt(p, end - p, t->sub[0]);
-            p += snprintf(p, end - p, "[:]");
+            p += bprintf(p, end - p, "[:]");
             break;
         case Tyarray:
             p += tybfmt(p, end - p, t->sub[0]);
             if (t->asize) {
                 i = t->asize->expr.args[0]->lit.intval;
-                p += snprintf(p, end - p, "[%zd]", i);
+                p += bprintf(p, end - p, "[%zd]", i);
             } else {
-                p += snprintf(p, end - p, "[]");
+                p += bprintf(p, end - p, "[]");
             }
             break;
         case Tyfunc:
-            p += snprintf(p, end - p, "(");
+            p += bprintf(p, end - p, "(");
             for (i = 1; i < t->nsub; i++) {
-                p += snprintf(p, end - p, "%s", sep);
+                p += bprintf(p, end - p, "%s", sep);
                 p += tybfmt(p, end - p, t->sub[i]);
                 sep = ", ";
             }
-            p += snprintf(p, end - p, " -> ");
+            p += bprintf(p, end - p, " -> ");
             p += tybfmt(p, end - p, t->sub[0]);
-            p += snprintf(p, end - p, ")");
+            p += bprintf(p, end - p, ")");
             break;
         case Tytuple:
-            p += snprintf(p, end - p, "(");
+            p += bprintf(p, end - p, "(");
             for (i = 0; i < t->nsub; i++) {
-                p += snprintf(p, end - p, "%s", sep);
+                p += bprintf(p, end - p, "%s", sep);
                 p += tybfmt(p, end - p, t->sub[i]);
                 sep = ",";
             }
-            p += snprintf(p, end - p, ")");
+            p += bprintf(p, end - p, ")");
             break;
         case Tyvar:
-            p += snprintf(p, end - p, "$%d", t->tid);
+            p += bprintf(p, end - p, "$%d", t->tid);
             if (t->nsub) {
-                p += snprintf(p, end - p, "(");
+                p += bprintf(p, end - p, "(");
                 for (i = 0; i < t->nsub; i++) {
-                    p += snprintf(p, end - p, "%s", sep);
+                    p += bprintf(p, end - p, "%s", sep);
                     p += tybfmt(p, end - p, t->sub[i]);
                     sep = ", ";
                 }
-                p += snprintf(p, end - p, ")[]");
+                p += bprintf(p, end - p, ")[]");
             }
             break;
         case Typaram:
-            p += snprintf(p, end - p, "@%s", t->pname);
+            p += bprintf(p, end - p, "@%s", t->pname);
             break;
         case Tyunres:
             p += namefmt(p, end - p, t->name);
@@ -606,15 +606,15 @@
             break;
         case Tyname:
             if (t->name->name.ns)
-                p += snprintf(p, end - p, "%s.", t->name->name.ns);
-            p += snprintf(p, end - p, "%s", namestr(t->name));
+                p += bprintf(p, end - p, "%s.", t->name->name.ns);
+            p += bprintf(p, end - p, "%s", namestr(t->name));
             if (t->narg)
                 p += fmtlist(p, end - p, t->arg, t->narg);
             break;
         case Tygeneric:
             if (t->name->name.ns)
-                p += snprintf(p, end - p, "%s.", t->name->name.ns);
-            p += snprintf(p, end - p, "%s", namestr(t->name));
+                p += bprintf(p, end - p, "%s.", t->name->name.ns);
+            p += bprintf(p, end - p, "%s", namestr(t->name));
             if (t->ngparam)
                 p += fmtlist(p, end - p, t->gparam, t->ngparam);
             break;
@@ -775,78 +775,78 @@
         case Ntypes:
         case Tybad:     die("invalid type");    break;
         case Tyvar:     die("tyvar has no idstr");      break;
-        case Tyvoid:    p += snprintf(p, end - p, "v");  break;
-        case Tychar:    p += snprintf(p, end - p, "c");  break;
-        case Tybool:    p += snprintf(p, end - p, "t");  break;
-        case Tyint8:    p += snprintf(p, end - p, "b");  break;
-        case Tyint16:   p += snprintf(p, end - p, "s");  break;
-        case Tyint:     p += snprintf(p, end - p, "i");  break;
-        case Tyint32:   p += snprintf(p, end - p, "w");  break;
-        case Tyint64:   p += snprintf(p, end - p, "q");  break;
-        case Tylong:    p += snprintf(p, end - p, "l");  break;
+        case Tyvoid:    p += bprintf(p, end - p, "v");  break;
+        case Tychar:    p += bprintf(p, end - p, "c");  break;
+        case Tybool:    p += bprintf(p, end - p, "t");  break;
+        case Tyint8:    p += bprintf(p, end - p, "b");  break;
+        case Tyint16:   p += bprintf(p, end - p, "s");  break;
+        case Tyint:     p += bprintf(p, end - p, "i");  break;
+        case Tyint32:   p += bprintf(p, end - p, "w");  break;
+        case Tyint64:   p += bprintf(p, end - p, "q");  break;
+        case Tylong:    p += bprintf(p, end - p, "l");  break;
 
-        case Tybyte:    p += snprintf(p, end - p, "H");  break;
-        case Tyuint8:   p += snprintf(p, end - p, "B");  break;
-        case Tyuint16:  p += snprintf(p, end - p, "S");  break;
-        case Tyuint:    p += snprintf(p, end - p, "I");  break;
-        case Tyuint32:  p += snprintf(p, end - p, "W");  break;
-        case Tyuint64:  p += snprintf(p, end - p, "Q");  break;
-        case Tyulong:   p += snprintf(p, end - p, "L");  break;
-        case Tyflt32:   p += snprintf(p, end - p, "f");  break;
-        case Tyflt64:   p += snprintf(p, end - p, "d");  break;
-        case Tyvalist:  p += snprintf(p, end - p, "V");  break;
+        case Tybyte:    p += bprintf(p, end - p, "H");  break;
+        case Tyuint8:   p += bprintf(p, end - p, "B");  break;
+        case Tyuint16:  p += bprintf(p, end - p, "S");  break;
+        case Tyuint:    p += bprintf(p, end - p, "I");  break;
+        case Tyuint32:  p += bprintf(p, end - p, "W");  break;
+        case Tyuint64:  p += bprintf(p, end - p, "Q");  break;
+        case Tyulong:   p += bprintf(p, end - p, "L");  break;
+        case Tyflt32:   p += bprintf(p, end - p, "f");  break;
+        case Tyflt64:   p += bprintf(p, end - p, "d");  break;
+        case Tyvalist:  p += bprintf(p, end - p, "V");  break;
         case Typtr:
-            p += snprintf(p, end - p, "$p");
+            p += bprintf(p, end - p, "$p");
             p += tyidfmt(p, end - p, ty->sub[0]);
             break;
         case Tyarray:
-            p += snprintf(p, end - p, "$a%lld", (vlong)arraysz(ty->asize));
+            p += bprintf(p, end - p, "$a%lld", (vlong)arraysz(ty->asize));
             p += tyidfmt(p, end - p, ty->sub[0]);
             break;
         case Tyslice:
-            p += snprintf(p, end - p, "$s");
+            p += bprintf(p, end - p, "$s");
             p += tyidfmt(p, end - p, ty->sub[0]);
             break;
         case Tyfunc:
-            p += snprintf(p, end - p, "$f");
+            p += bprintf(p, end - p, "$f");
             for (i = 0; i < ty->nsub; i++) {
                 p += tyidfmt(p, end - p, ty->sub[i]);
-                p += snprintf(p, end - p, "$");
+                p += bprintf(p, end - p, "$");
             }
             break;
         case Tytuple:
-            p += snprintf(p, end - p, "$e");
+            p += bprintf(p, end - p, "$e");
             for (i = 0; i < ty->nsub; i++) {
                 p += tyidfmt(p, end - p, ty->sub[i]);
             }
-            p += snprintf(p, end - p, "$");
+            p += bprintf(p, end - p, "$");
             break;
         case Tystruct:
-            p += snprintf(p, end - p, "$t");
+            p += bprintf(p, end - p, "$t");
             for (i = 0; i < ty->nmemb; i++) {
-                p += snprintf(p, end - p, "%s.", declname(ty->sdecls[i]));
+                p += bprintf(p, end - p, "%s.", declname(ty->sdecls[i]));
                 p += tyidfmt(p, end - p, decltype(ty->sdecls[i]));
-                p += snprintf(p, end - p, "$");
+                p += bprintf(p, end - p, "$");
             }
             break;
         case Tyunion:
-            p += snprintf(p, end - p, "$u");
+            p += bprintf(p, end - p, "$u");
             for (i = 0; i < ty->nmemb; i++) {
-                p += snprintf(p, end - p, "%s$", namestr(ty->udecls[i]->name));
+                p += bprintf(p, end - p, "%s$", namestr(ty->udecls[i]->name));
                 if (ty->udecls[i]->etype)
                     p += tyidfmt(p, end - p, ty->udecls[i]->etype);
-                p += snprintf(p, end - p, "$");
+                p += bprintf(p, end - p, "$");
             }
             break;
         case Typaram:
-            p += snprintf(p, end - p, "$r%s", ty->pname);
+            p += bprintf(p, end - p, "$r%s", ty->pname);
             break;
         case Tyunres:
         case Tyname:
-            p += snprintf(p, end - p, "$n");
+            p += bprintf(p, end - p, "$n");
             if (ty->name->name.ns)
-                p += snprintf(p, end - p, "%s", ty->name->name.ns);
-            p += snprintf(p, end - p, "$%s", ty->name->name.name);
+                p += bprintf(p, end - p, "%s", ty->name->name.ns);
+            p += bprintf(p, end - p, "$%s", ty->name->name.name);
             if (ty->arg)
                 for (i = 0; i < ty->narg; i++)
                     p += tyidfmt(p, end - p, ty->arg[i]);
--- a/parse/util.c
+++ b/parse/util.c
@@ -109,7 +109,7 @@
 
     n = strlen(u) + strlen(v) + 1;
     s = xalloc(n);
-    snprintf(s, n + 1, "%s%s", u, v);
+    bprintf(s, n + 1, "%s%s", u, v);
     return s;
 }
 
@@ -358,6 +358,19 @@
     return u.fval;
 }
 
+size_t bprintf(char *buf, size_t sz, char *fmt, ...)
+{
+    va_list ap;
+    size_t n;
+
+    va_start(ap, fmt);
+    n = vsnprintf(buf, sz, fmt, ap);
+    assert(n <= sz);
+    va_end(ap);
+
+    return n;
+}
+
 void wrbool(FILE *fd, int val)
 {
     wrbyte(fd, val);
@@ -387,7 +400,7 @@
         strncat(buf, s, slen - suflen);
         strncat(buf, swap, swaplen);
     } else {
-        snprintf(buf, sz, "%s%s", s, swap);
+        bprintf(buf, sz, "%s%s", s, swap);
     }
 
     return buf;