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.
This commit is contained in:
Markus Armbruster 2013-01-13 10:32:54 +01:00
parent 9da83c54c0
commit bc14b41c65

View file

@ -29,7 +29,7 @@
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1989 * Dave Pare, 1989
* Steve McClure, 2000 * Steve McClure, 2000
* Markus Armbruster, 2005-2012 * Markus Armbruster, 2005-2013
*/ */
#include <config.h> #include <config.h>
@ -85,6 +85,8 @@ ef_open(int type, int how)
ep = &empfile[type]; ep = &empfile[type];
if (CANT_HAPPEN(!ep->file || ep->base != EF_BAD || ep->fd >= 0)) if (CANT_HAPPEN(!ep->file || ep->base != EF_BAD || ep->fd >= 0))
return 0; return 0;
if (CANT_HAPPEN(ep->prewrite && !(how & EFF_MEM)))
return 0; /* not implemented */
oflags = O_RDWR; oflags = O_RDWR;
if (how & EFF_PRIVATE) if (how & EFF_PRIVATE)
oflags = O_RDONLY; oflags = O_RDONLY;
@ -542,6 +544,8 @@ ef_write(int type, int id, void *from)
ep = &empfile[type]; ep = &empfile[type];
if (CANT_HAPPEN((ep->flags & (EFF_MEM | EFF_PRIVATE)) == EFF_PRIVATE)) if (CANT_HAPPEN((ep->flags & (EFF_MEM | EFF_PRIVATE)) == EFF_PRIVATE))
return 0; return 0;
if (CANT_HAPPEN(id < 0))
return 0;
if (CANT_HAPPEN(ep->nent >= 0 && id >= ep->nent)) if (CANT_HAPPEN(ep->nent >= 0 && id >= ep->nent))
return 0; /* beyond fixed size */ return 0; /* beyond fixed size */
new_seqno(ep, from); new_seqno(ep, from);
@ -966,9 +970,8 @@ ef_check(int type)
int int
ef_ensure_space(int type, int id, int count) 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; return 0;
CANT_HAPPEN(id < 0);
while (id >= empfile[type].fids) { while (id >= empfile[type].fids) {
if (!ef_extend(type, count)) if (!ef_extend(type, count))