Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Mar 2009 17:17:06 GMT
From:      Nate Eldredge <neldredge@math.ucsd.edu>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   bin/132735: Berkeley db: corrupted file has record with absurd size
Message-ID:  <200903171717.n2HHH6b6089689@www.freebsd.org>
Resent-Message-ID: <200903171720.n2HHK5K1024205@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         132735
>Category:       bin
>Synopsis:       Berkeley db: corrupted file has record with absurd size
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 17 17:20:05 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Nate Eldredge
>Release:        7.1-RELEASE-p3
>Organization:
>Environment:
FreeBSD vulcan.lan 7.1-RELEASE-p3 FreeBSD 7.1-RELEASE-p3 #1: Mon Feb 23 14:45:27 PST 2009     root@vulcan.lan:/usr/obj/usr/src/sys/VULCAN  amd64

>Description:
Hi,

I have a Berkeley db file that is corrupted somehow, and when read with the db routines (dbopen(3)) from libc, returns bogus data that results in a crash.

The file is available at http://www.math.ucsd.edu/~neldredg/testcase.db .  It was produced by the recovery mechanism of vi(1), possibly while the system was crashing (I was working on a kernel bug at the time).

Is this normal behavior for db when the input file is corrupted, or is it supposed to be more robust?
>How-To-Repeat:
I wrote the following test program:

#include <sys/types.h>
#include <db.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

void dump_dbt(const DBT *dbt) {
  printf("(%zu)", dbt->size);
  size_t i;
  unsigned char *p = dbt->data;
  for (i = 0; i < dbt->size; i++)
    printf(" %02x", p[i]);
  printf("\n");
}

int main(int argc, char *argv[]) {
  if (argc < 2) {
    fprintf(stderr, "Usage: %s filename\n", argv[0]);
    exit(2);
  }
  setvbuf(stdout, NULL, _IONBF, 0);
  DB *db = dbopen(argv[1], O_RDONLY, 0, DB_BTREE, NULL);
  if (!db) {
    perror("dbopen");
    exit(1);
  }
  
  int ret;
  DBT key, data;
  while ((ret = db->seq(db, &key, &data, R_NEXT)) == 0) {
    printf("Key: ");
    dump_dbt(&key);
    printf("Data: ");
    dump_dbt(&data);
  }
  if (ret != 1) {
    perror("db->seq");
    if (ret != -1) {
      fprintf(stderr, "Unexpected ret == %d\n", ret);
    }
    exit(1);
  }
  return 0;
}

When run on testcase.db, the output is:

Key: (3) 00 00 00
Data: (757739264) 00 00 00 00 00 [...]

followed by a segfault, since there obviously aren't 757739264 bytes of data in the file.
>Fix:


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903171717.n2HHH6b6089689>