[PECL-CVS] [pecl-text-xdiff] fix-memory-issues: memory safety cleanup
[email protected] (Rasmus Lerdorf) Sun, 5 Apr 2026 17:59:44 +0000
| Newsgroups | php.pecl.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: Rasmus Lerdorf (rlerdorf)
Date: 2026-04-05T13:59:29-04:00
Commit: https://github.com/php/pecl-text-xdiff/commit/446c7babed510ae34e93516579f364c6b983f4f7
Raw diff: https://github.com/php/pecl-text-xdiff/commit/446c7babed510ae34e93516579f364c6b983f4f7.diff
memory safety cleanup
Changed paths:
A tests/file_bpatch_retval.phpt
M xdiff.c
Diff:
diff --git a/tests/file_bpatch_retval.phpt b/tests/file_bpatch_retval.phpt
new file mode 100644
index 0000000..e0f8eda
--- /dev/null
+++ b/tests/file_bpatch_retval.phpt
@@ -0,0 +1,21 @@
+--TEST--
+xdiff_file_bpatch() return value on success and failure
+--SKIPIF--
+<?php if (!extension_loaded("xdiff")) print "skip"; ?>
+--FILE--
+<?php
+$result = xdiff_file_bpatch(__DIR__ . '/file.1', __DIR__ . '/file.bdiff', __DIR__ . '/file.bpatch_out');
+var_dump($result);
+$a = file_get_contents(__DIR__ . '/file.2');
+$b = file_get_contents(__DIR__ . '/file.bpatch_out');
+echo "content match: " . (strcmp($a, $b) === 0 ? "yes" : "no") . "\n";
+unlink(__DIR__ . '/file.bpatch_out');
+
+$result = xdiff_file_bpatch(__DIR__ . '/file.1', __DIR__ . '/file.1', __DIR__ . '/file.bpatch_out2');
+var_dump($result);
+@unlink(__DIR__ . '/file.bpatch_out2');
+?>
+--EXPECT--
+bool(true)
+content match: yes
+bool(false)
diff --git a/xdiff.c b/xdiff.c
index 9b0f8c3..ce67501 100644
--- a/xdiff.c
+++ b/xdiff.c
@@ -82,17 +82,17 @@ static int init_string(struct string_buffer *string);
static void free_string(struct string_buffer *string);
static int make_diff(char *filepath1, char *filepath2, xdemitcb_t *output, int context, int minimal);
-static int make_diff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output, int context, int minimal);
+static int make_diff_str(char *str1, size_t size1, char *str2, size_t size2, xdemitcb_t *output, int context, int minimal);
static int make_bdiff(char *filepath1, char *filepath2, xdemitcb_t *output);
-static int make_bdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output);
+static int make_bdiff_str(char *str1, size_t size1, char *str2, size_t size2, xdemitcb_t *output);
static int make_patch(char *file_path, char *patch_path, xdemitcb_t *output, xdemitcb_t *error, int flags);
-static int make_patch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output, xdemitcb_t *error, int flags);
+static int make_patch_str(char *file, size_t size1, char *patch, size_t size2, xdemitcb_t *output, xdemitcb_t *error, int flags);
static int make_bpatch(char *file_path, char *patch_path, xdemitcb_t *output);
-static int make_bpatch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output);
+static int make_bpatch_str(char *file, size_t size1, char *patch, size_t size2, xdemitcb_t *output);
static int make_merge3(char *filepath1, char *filepath2, char *filepath3, xdemitcb_t *output, xdemitcb_t *error);
-static int make_merge3_str(char *content1, int size1, char *content2, int size2, char *content3, int size3, xdemitcb_t *output, xdemitcb_t *error);
+static int make_merge3_str(char *content1, size_t size1, char *content2, size_t size2, char *content3, size_t size3, xdemitcb_t *output, xdemitcb_t *error);
static int make_rabdiff(char *filepath1, char *filepath2, xdemitcb_t *output);
-static int make_rabdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output);
+static int make_rabdiff_str(char *str1, size_t size1, char *str2, size_t size2, xdemitcb_t *output);
static void *xdiff_malloc(void *foo, unsigned int size)
{
@@ -187,8 +187,13 @@ PHP_FUNCTION(xdiff_string_diff)
output.priv= &string;
output.outf = append_string;
- make_diff_str(str1->val, str1->len, str2->val, str2->len, &output, context, minimal);
+ retval = make_diff_str(str1->val, str1->len, str2->val, str2->len, &output, context, minimal);
+ if (!retval)
+ goto out_free_string;
+
RETVAL_STRINGL(string.ptr, string.size);
+
+out_free_string:
free_string(&string);
out:
return;
@@ -254,10 +259,14 @@ PHP_FUNCTION(xdiff_string_bdiff)
output.priv= &string;
output.outf = append_string;
- make_bdiff_str(str1->val, str1->len, str2->val, str2->len, &output);
+ retval = make_bdiff_str(str1->val, str1->len, str2->val, str2->len, &output);
+ if (!retval)
+ goto out_free_string;
+
RETVAL_STRINGL(string.ptr, string.size);
- free_string(&string);
+out_free_string:
+ free_string(&string);
out:
return;
}
@@ -320,10 +329,14 @@ PHP_FUNCTION(xdiff_string_rabdiff)
output.priv= &string;
output.outf = append_string;
- make_rabdiff_str(str1->val, str1->len, str2->val, str2->len, &output);
+ retval = make_rabdiff_str(str1->val, str1->len, str2->val, str2->len, &output);
+ if (!retval)
+ goto out_free_string;
+
RETVAL_STRINGL(string.ptr, string.size);
- free_string(&string);
+out_free_string:
+ free_string(&string);
out:
return;
}
@@ -557,7 +570,7 @@ PHP_FUNCTION(xdiff_file_bpatch)
retval = make_bpatch(src_path->val, patch_path->val, &output);
php_stream_close(output_stream);
- if (retval == 0)
+ if (retval)
RETVAL_TRUE;
out:
@@ -728,7 +741,9 @@ static int load_mm_file(const char *filepath, mmfile_t *dest)
if (!ptr)
goto out_free_mmfile;
- php_stream_read(src, ptr, filesize);
+ if (php_stream_read(src, ptr, filesize) != filesize)
+ goto out_free_mmfile;
+
php_stream_close(src);
return 1;
@@ -773,6 +788,7 @@ static int append_string(void *ptr, mmbuffer_t *buffer, int array_size)
new_ptr = erealloc(string->ptr, string->size + buffer[i].size + 1);
if (!new_ptr) {
efree(string->ptr);
+ string->ptr = NULL;
return -1;
}
@@ -849,7 +865,7 @@ static int make_diff(char *filepath1, char *filepath2, xdemitcb_t *output, int c
return result;
}
-static int make_diff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output, int context, int minimal)
+static int make_diff_str(char *str1, size_t size1, char *str2, size_t size2, xdemitcb_t *output, int context, int minimal)
{
mmfile_t file1, file2;
xpparam_t params;
@@ -911,7 +927,7 @@ static int make_bdiff(char *filepath1, char *filepath2, xdemitcb_t *output)
return result;
}
-static int make_bdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output)
+static int make_bdiff_str(char *str1, size_t size1, char *str2, size_t size2, xdemitcb_t *output)
{
mmfile_t file1, file2;
bdiffparam_t params;
@@ -968,7 +984,7 @@ static int make_rabdiff(char *filepath1, char *filepath2, xdemitcb_t *output)
return result;
}
-static int make_rabdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output)
+static int make_rabdiff_str(char *str1, size_t size1, char *str2, size_t size2, xdemitcb_t *output)
{
mmfile_t file1, file2;
int retval, result = 0;
@@ -1022,7 +1038,7 @@ static int make_patch(char *file_path, char *patch_path, xdemitcb_t *output, xde
return result;
}
-static int make_patch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output, xdemitcb_t *error, int flags)
+static int make_patch_str(char *file, size_t size1, char *patch, size_t size2, xdemitcb_t *output, xdemitcb_t *error, int flags)
{
mmfile_t file_mm, patch_mm;
int retval, result = 0;
@@ -1076,7 +1092,7 @@ static int make_bpatch(char *file_path, char *patch_path, xdemitcb_t *output)
return result;
}
-static int make_bpatch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output)
+static int make_bpatch_str(char *file, size_t size1, char *patch, size_t size2, xdemitcb_t *output)
{
mmfile_t file_mm, patch_mm;
int retval, result = 0;
@@ -1136,7 +1152,7 @@ static int make_merge3(char *filepath1, char *filepath2, char *filepath3, xdemit
return result;
}
-static int make_merge3_str(char *content1, int size1, char *content2, int size2, char *content3, int size3, xdemitcb_t *output, xdemitcb_t *error)
+static int make_merge3_str(char *content1, size_t size1, char *content2, size_t size2, char *content3, size_t size3, xdemitcb_t *output, xdemitcb_t *error)
{
mmfile_t file1, file2, file3;
int retval, result = 0;