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.
* Known contributors to this file:
* Dave Pare, 1989
* Steve McClure, 2000
* Known contributors to this file:
* Dave Pare, 1989
* Steve McClure, 2000
- * Markus Armbruster, 2005-2012
+ * Markus Armbruster, 2005-2013
ep = &empfile[type];
if (CANT_HAPPEN(!ep->file || ep->base != EF_BAD || ep->fd >= 0))
return 0;
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;
oflags = O_RDWR;
if (how & EFF_PRIVATE)
oflags = O_RDONLY;
ep = &empfile[type];
if (CANT_HAPPEN((ep->flags & (EFF_MEM | EFF_PRIVATE)) == EFF_PRIVATE))
return 0;
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);
if (CANT_HAPPEN(ep->nent >= 0 && id >= ep->nent))
return 0; /* beyond fixed size */
new_seqno(ep, from);
int
ef_ensure_space(int type, int id, int count)
{
int
ef_ensure_space(int type, int id, int count)
{
- if (ef_check(type) < 0)
+ if (ef_check(type) < 0 || CANT_HAPPEN(id < 0))
while (id >= empfile[type].fids) {
if (!ef_extend(type, count))
while (id >= empfile[type].fids) {
if (!ef_extend(type, count))