From 7ba9f9467d95fa8d05bb04d36fd4c602e497f529 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 13 Jan 2020 11:41:37 -0500 Subject: lib9/fmt: avoid racy access to installed fmt formats --- src/lib9/fmt/fmt.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'src/lib9/fmt/fmt.c') diff --git a/src/lib9/fmt/fmt.c b/src/lib9/fmt/fmt.c index 66093fd0..9c3f45d3 100644 --- a/src/lib9/fmt/fmt.c +++ b/src/lib9/fmt/fmt.c @@ -72,7 +72,7 @@ static Convfmt knownfmt[] = { int (*fmtdoquote)(int); /* - * __fmtlock() must be set + * __fmtwlock() must be set */ static int __fmtinstall(int c, Fmts f) @@ -106,34 +106,43 @@ fmtinstall(int c, int (*f)(Fmt*)) { int ret; - __fmtlock(); + __fmtwlock(); ret = __fmtinstall(c, f); - __fmtunlock(); + __fmtwunlock(); return ret; } static Fmts fmtfmt(int c) { - Convfmt *p, *ep; + Convfmt *p, *ep, *kp; + /* conflict-free check - common case */ + __fmtrlock(); ep = &fmtalloc.fmt[fmtalloc.nfmt]; for(p=fmtalloc.fmt; pc == c){ - while(p->fmt == nil) /* loop until value is updated */ - ; + __fmtrunlock(); return p->fmt; } + __fmtrunlock(); /* is this a predefined format char? */ - __fmtlock(); - for(p=knownfmt; p->c; p++) - if(p->c == c){ - __fmtinstall(p->c, p->fmt); - __fmtunlock(); - return p->fmt; + for(kp=knownfmt; kp->c; kp++){ + if(kp->c == c){ + __fmtwlock(); + /* double-check fmtinstall didn't happen */ + for(p=fmtalloc.fmt; pc == c){ + __fmtwunlock(); + return p->fmt; + } + } + __fmtinstall(kp->c, kp->fmt); + __fmtwunlock(); + return kp->fmt; } - __fmtunlock(); + } return __badfmt; } -- cgit v1.2.3