From: Markus Armbruster Date: Sun, 13 Jan 2013 09:32:54 +0000 (+0100) Subject: Fix crash on edit s, p, u key 'U' with negative argument X-Git-Tag: v4.3.31~75 X-Git-Url: http://git.pond.sub.org/?p=empserver;a=commitdiff_plain;h=bc14b41c6522ecebda67f599435f000354dbe69a Fix crash on edit s, p, u key 'U' with negative argument ef_ensure_space() oopses on negative ID, but succeeds anyway. edit() proceeds to ef_write(), which neglects to check for negative ID. Since the ID isn't in the cache, it then passes a NULL old element to callback prewrite(), which crashes. Fix ef_ensure_space() to fail on negative ID. Commit 5173f8cd (v4.3.0) made it oops, but neglected to make it fail. Fix ef_write() to oops and fail on negative ID. ef_write() still passes NULL old element to prewrite() when the ID isn't in the cache. Doesn't actually happen, because we use prewrite() callbacks only with fully cached tables. Fragile. Make ef_open() fail when that assumption is violated. --- diff --git a/src/lib/common/file.c b/src/lib/common/file.c index 31f8f0fd7..e985ce65d 100644 --- a/src/lib/common/file.c +++ b/src/lib/common/file.c @@ -29,7 +29,7 @@ * Known contributors to this file: * Dave Pare, 1989 * Steve McClure, 2000 - * Markus Armbruster, 2005-2012 + * Markus Armbruster, 2005-2013 */ #include @@ -85,6 +85,8 @@ ef_open(int type, int how) ep = &empfile[type]; if (CANT_HAPPEN(!ep->file || ep->base != EF_BAD || ep->fd >= 0)) return 0; + if (CANT_HAPPEN(ep->prewrite && !(how & EFF_MEM))) + return 0; /* not implemented */ oflags = O_RDWR; if (how & EFF_PRIVATE) oflags = O_RDONLY; @@ -542,6 +544,8 @@ ef_write(int type, int id, void *from) ep = &empfile[type]; if (CANT_HAPPEN((ep->flags & (EFF_MEM | EFF_PRIVATE)) == EFF_PRIVATE)) return 0; + if (CANT_HAPPEN(id < 0)) + return 0; if (CANT_HAPPEN(ep->nent >= 0 && id >= ep->nent)) return 0; /* beyond fixed size */ new_seqno(ep, from); @@ -966,9 +970,8 @@ ef_check(int type) int ef_ensure_space(int type, int id, int count) { - if (ef_check(type) < 0) + if (ef_check(type) < 0 || CANT_HAPPEN(id < 0)) return 0; - CANT_HAPPEN(id < 0); while (id >= empfile[type].fids) { if (!ef_extend(type, count))