Fix #81563: SIGSEGV reading dbase file with few data

When reading a field descriptor array, we must not assume to actually
read the full array, but rather be prepared to only read the field
terminator.  We also must not return arbitrary values, since the caller
is not prepared for that; only `0`, `2` and negative values are
supported.
This commit is contained in:
Christoph M. Becker
2021-10-29 17:37:01 +02:00
parent f4091907b7
commit 4259c681c1
4 changed files with 39 additions and 2 deletions

View File

@@ -165,14 +165,15 @@ int put_dbf_head(dbhead_t *dbh)
/*
* get a field off the disk from the current file offset
* returns 0 on success, 2 on field terminator and -1 on failure
*/
int get_dbf_field(dbhead_t *dbh, dbfield_t *dbf)
{
struct dbf_dfield dbfield;
int ret;
if ((ret = read(dbh->db_fd, &dbfield, sizeof(dbfield))) != sizeof(dbfield)) {
return ret;
if ((ret = read(dbh->db_fd, &dbfield, sizeof(dbfield))) <= 0) {
return -1;
}
/* Check for the '0Dh' field terminator , if found return '2'
@@ -181,6 +182,10 @@ int get_dbf_field(dbhead_t *dbh, dbfield_t *dbf)
return 2;
}
if (ret != sizeof(dbfield)) {
return -1;
}
/* build the field name */
copy_crimp(dbf->db_fname, dbfield.dbf_name, DBF_NAMELEN);

View File

@@ -53,6 +53,7 @@ are kept until you call dbase_pack().
Bug Fixes
- Fixed GH-1 (dbase_add_record() converts passed floats and leaks memory)
- Fixed #81563 (SIGSEGV reading dbase file with few data)
]]>
</notes>
@@ -96,6 +97,8 @@ Bug Fixes
<file name="bug78668.phpt" role="test" />
<file name="bug78668_8.phpt" role="test" />
<file name="bug80156.phpt" role="test" />
<file name="bug81563.dbf" role="test" />
<file name="bug81563.phpt" role="test" />
<file name="dbase_add_record_basic.phpt" role="test" />
<file name="dbase_add_record_error.phpt" role="test" />
<file name="dbase_add_record_error-8.phpt" role="test" />

BIN
tests/bug81563.dbf Normal file

Binary file not shown.

29
tests/bug81563.phpt Normal file
View File

@@ -0,0 +1,29 @@
--TEST--
Bug #81563 (SIGSEGV reading dbase file with few data)
--SKIPIF--
<?php
if (!extension_loaded("dbase")) die("skip dbase extension not available");
?>
--FILE--
<?php
$filename = __DIR__ . "/bug81563.dbf";
$db = dbase_open($filename, 0);
$n = dbase_numrecords($db);
for ($index = 1; $index <= $n; $index++) {
$record = dbase_get_record_with_names($db, $index);
var_dump($record);
}
dbase_close($db);
?>
--EXPECT--
array(4) {
["SCHLAGNR"]=>
int(12345)
["TEILSCHLAG"]=>
string(2) "a "
["FLIK"]=>
string(16) "DENWLI0546132777"
["deleted"]=>
int(0)
}