[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pecl-cvs
Subject:    [PECL-CVS] [pecl-database-dbase] master: Fix #81563: SIGSEGV reading dbase file with few data
From:       "Christoph M. Becker" <noreply () php ! net>
Date:       2021-10-29 15:36:41
Message-ID: otqPwtIrTlU82k78Io9zMq1l1Azi9Lw9cMDWY0LwY () main ! php ! net
[Download RAW message or body]

Author: Christoph M. Becker (cmb69)
Date: 2021-10-29T17:37:01+02:00

Commit: https://github.com/php/pecl-database-dbase/commit/4259c681c11fe60c9347d79a573b95c7ea2c5b4e
Raw diff: https://github.com/php/pecl-database-dbase/commit/4259c681c11fe60c9347d79a573b95c7ea2c5b4e.diff

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.

Changed paths:
  A  tests/bug81563.dbf
  A  tests/bug81563.phpt
  M  dbf_head.c
  M  package.xml


Diff:

diff --git a/dbf_head.c b/dbf_head.c
index 1a80f7d..8f1c0ab 100644
--- a/dbf_head.c
+++ b/dbf_head.c
@@ -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);
 
diff --git a/package.xml b/package.xml
index 5e23a1b..eada0f5 100644
--- a/package.xml
+++ b/package.xml
@@ -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" />
diff --git a/tests/bug81563.dbf b/tests/bug81563.dbf
new file mode 100644
index 0000000..699e20f
Binary files /dev/null and b/tests/bug81563.dbf differ
diff --git a/tests/bug81563.phpt b/tests/bug81563.phpt
new file mode 100644
index 0000000..68d1bf2
--- /dev/null
+++ b/tests/bug81563.phpt
@@ -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)
+}

-- 
PECL CVS Mailing List 
To unsubscribe, visit: http://www.php.net/unsub.php

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic