Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion syslog_alerts.php
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,20 @@ function import() {
}

function alert_import() {
$xml_data = syslog_get_import_xml_payload('syslog_alerts.php?header=false');
$import_text = get_nfilter_request_var('import_text');

if (trim($import_text) != '') {
/* textbox input */
$xml_data = $import_text;
} elseif (($_FILES['import_file']['tmp_name'] != 'none') && ($_FILES['import_file']['tmp_name'] != '')) {
/* file upload */
$fp = fopen($_FILES['import_file']['tmp_name'],'r');
$xml_data = fread($fp, filesize($_FILES['import_file']['tmp_name']));
fclose($fp);
} else {
header('Location: syslog_alerts.php?header=false');
exit;
}

$xml_array = xml2array($xml_data);

Expand Down
15 changes: 14 additions & 1 deletion syslog_removal.php
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,20 @@ function import() {
}

function removal_import() {
$xml_data = syslog_get_import_xml_payload('syslog_removal.php?header=false');
$import_text = get_nfilter_request_var('import_text');

if (trim($import_text) != '') {
/* textbox input */
$xml_data = $import_text;
} elseif (($_FILES['import_file']['tmp_name'] != 'none') && ($_FILES['import_file']['tmp_name'] != '')) {
/* file upload */
$fp = fopen($_FILES['import_file']['tmp_name'],'r');
$xml_data = fread($fp, filesize($_FILES['import_file']['tmp_name']));
fclose($fp);
} else {
header('Location: syslog_removal.php?header=false');
exit;
}

/* obtain debug information if it's set */
$xml_array = xml2array($xml_data);
Expand Down
15 changes: 14 additions & 1 deletion syslog_reports.php
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,20 @@ function import() {
}

function report_import() {
$xml_data = syslog_get_import_xml_payload('syslog_reports.php?header=false');
$import_text = get_nfilter_request_var('import_text');

if (trim($import_text) != '') {
/* textbox input */
$xml_data = $import_text;
} elseif (($_FILES['import_file']['tmp_name'] != 'none') && ($_FILES['import_file']['tmp_name'] != '')) {
/* file upload */
$fp = fopen($_FILES['import_file']['tmp_name'],'r');
$xml_data = fread($fp, filesize($_FILES['import_file']['tmp_name']));
fclose($fp);
} else {
header('Location: syslog_reports.php?header=false');
exit;
}

/* obtain debug information if it's set */
$xml_array = xml2array($xml_data);
Expand Down
68 changes: 68 additions & 0 deletions tests/regression/issue269_import_text_branch_logic_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

/*
* Regression test for issue #269 -- branch-logic invariants.
*
* These assertions verify the structural properties that make whitespace-only
* input fall through to the file-upload branch instead of the textbox branch,
* and that a non-empty payload is assigned to $xml_data without further
* modification. Pure source inspection: the functions themselves cannot be
* called in isolation because they depend on the Cacti runtime.
*/

$root = dirname(__DIR__, 2);
$targets = array(
'alert_import' => $root . '/syslog_alerts.php',
'removal_import' => $root . '/syslog_removal.php',
'report_import' => $root . '/syslog_reports.php',
);

foreach ($targets as $func => $target) {
$content = file_get_contents($target);

if ($content === false) {
fwrite(STDERR, "Failed to load $target\n");
exit(1);
}

/*
* 1. The request variable must be captured into a local first.
* Whitespace-only input falls through only because trim() is applied
* to the local; if the assignment were missing the condition would
* be wrong.
*/
if (!preg_match('/\$import_text\s*=\s*get_nfilter_request_var\s*\(\s*\'import_text\'\s*\)/', $content)) {
fwrite(STDERR, "$func: \$import_text assignment via get_nfilter_request_var missing in $target\n");
exit(1);
}

/*
* 2. The branch condition must trim the local variable, not the raw
* request call. This is what makes whitespace-only values fall
* through to the file-upload branch.
*/
if (!preg_match('/trim\s*\(\s*\$import_text\s*\)\s*!=\s*\'\'/', $content)) {
fwrite(STDERR, "$func: trim(\$import_text) != '' condition missing in $target\n");
exit(1);
}

/*
* 3. Inside the textbox branch, $xml_data must be assigned the
* untrimmed local. A non-empty payload is preserved as-is.
*/
if (!preg_match('/\$xml_data\s*=\s*\$import_text\s*;/', $content)) {
fwrite(STDERR, "$func: \$xml_data = \$import_text assignment missing in $target\n");
exit(1);
}

/*
* 4. The file-upload branch must still exist (elseif on $_FILES).
* Ensures the fallback path was not accidentally removed.
*/
if (!preg_match('/elseif\s*\(\s*\(\s*\$_FILES\s*\[/', $content)) {
fwrite(STDERR, "$func: \$_FILES elseif branch missing in $target\n");
exit(1);
}
}

echo "issue269_import_text_branch_logic_test passed\n";
45 changes: 45 additions & 0 deletions tests/regression/issue269_import_text_trim_check_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

$root = dirname(__DIR__, 2);
$targets = array(
$root . '/syslog_alerts.php',
$root . '/syslog_reports.php',
$root . '/syslog_removal.php'
);

$legacy = "trim(get_nfilter_request_var('import_text') != '')";

foreach ($targets as $target) {
$content = file_get_contents($target);

if ($content === false) {
fwrite(STDERR, "Failed to load $target\n");
exit(1);
}

if (strpos($content, $legacy) !== false) {
fwrite(STDERR, "Legacy import_text trim/comparison bug remains in $target\n");
exit(1);
}

$fixedPattern = '/trim\s*\(\s*\$import_text\s*\)\s*!=\s*\'\'/';
if (!preg_match($fixedPattern, $content)) {
fwrite(STDERR, "Fixed import_text trim/comparison check missing in $target\n");
exit(1);
}

/* After the local $import_text assignment, there must be no second
get_nfilter_request_var('import_text') call. A duplicate call
would bypass the cached local variable. */
$needle = "\$import_text = get_nfilter_request_var('import_text')";
$assignPos = strpos($content, $needle);
if ($assignPos !== false) {
$afterAssign = substr($content, $assignPos + strlen($needle));
if (preg_match('/get_nfilter_request_var\s*\(\s*\'import_text\'\s*\)/', $afterAssign)) {
fwrite(STDERR, "Redundant get_nfilter_request_var('import_text') call after local assignment in $target\n");
exit(1);
}
}
}

echo "issue269_import_text_trim_check_test passed\n";
Loading