forked from Wavyzz/dolibarr
More explicit reporting for NOT IN sql forge notices
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/* Copyright (C) 2013 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2023 Alexandre Janniaux <alexandre.janniaux@gmail.com>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -497,36 +497,40 @@ class CodingPhpTest extends CommonClassTest
|
||||
|
||||
// Checks with IN
|
||||
|
||||
// Check string ' IN (".xxx' or ' IN (\'.xxx' with xxx that is not '$this->db->sanitize' and not '$db->sanitize'. It means we forget a db->sanitize when forging sql request.
|
||||
// Check string ' IN (".xxx' or ' IN (\'.xxx' with xxx that is not '$this->db->sanitize' and not '$db->sanitize'. It means we forgot a db->sanitize when forging a sql request.
|
||||
$ok = true;
|
||||
$lines = array();
|
||||
$matches = array();
|
||||
preg_match_all('/\s+IN\s*\([\'"]\s*\.\s*(.........)/i', $filecontent, $matches, PREG_SET_ORDER);
|
||||
preg_match_all('/\s+IN\s*\([\'"]\s*\.\s*(.........)(.*)/i', $filecontent, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $key => $val) {
|
||||
//var_dump($val);
|
||||
if (!in_array($val[1], array('$db->sani', '$this->db', 'getEntity', 'WON\',\'L', 'self::STA', 'Commande:', 'CommandeF', 'Entrepot:', 'Facture::', 'FactureFo', 'ExpenseRe', 'Societe::', 'Ticket::S'))) {
|
||||
$lines[] = self::reportAndGetLine($val[1].$val[2], $filecontent, $report_filepath, "NotSanitizedString in IN/NOT IN sql query `{$val[1]}{$val[2]}...`)");
|
||||
$ok = false;
|
||||
break;
|
||||
// break; // Not breaking, report all lines
|
||||
}
|
||||
//if ($reg[0] != 'db') $ok=false;
|
||||
}
|
||||
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
|
||||
$this->assertTrue($ok, 'Found non sanitized string in building of a IN or NOT IN sql request '.$file['relativename'].' - Bad.');
|
||||
$this->assertTrue($ok, 'Found non sanitized string in building of a IN or NOT IN sql request '.$file['relativename'].' - Bad. Lines:'.implode(',', $lines));
|
||||
//exit;
|
||||
|
||||
// Check string ' IN (\'".xxx' with xxx that is not '$this->db->sanitize' and not '$db->sanitize'. It means we forget a db->sanitize when forging sql request.
|
||||
// Check string ' IN (\'".xxx' with xxx that is not '$this->db->sanitize' and not '$db->sanitize'. It means we forgot a db->sanitize when forging a sql request.
|
||||
$ok = true;
|
||||
$lines = array();
|
||||
$matches = array();
|
||||
preg_match_all('/\s+IN\s*\(\'"\s*\.\s*(.........)/i', $filecontent, $matches, PREG_SET_ORDER);
|
||||
preg_match_all('/\s+IN\s*\(\'"\s*\.\s*(.........)(.*)/i', $filecontent, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $key => $val) {
|
||||
//var_dump($val);
|
||||
if (!in_array($val[1], array('$db->sani', '$this->db', 'getEntity', 'WON\',\'L', 'self::STA', 'Commande:', 'CommandeF', 'Entrepot:', 'Facture::', 'FactureFo', 'ExpenseRe', 'Societe::', 'Ticket::S'))) {
|
||||
$lines[] = self::reportAndGetLine($val[1].$val[2], $filecontent, $report_filepath, "NotSanitizedString in IN/NOT IN sql query `{$val[1]}{$val[2]}...`)");
|
||||
$ok = false;
|
||||
break;
|
||||
// break; // Not breaking, report all lines
|
||||
}
|
||||
//if ($reg[0] != 'db') $ok=false;
|
||||
}
|
||||
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
|
||||
$this->assertTrue($ok, 'Found non sanitized string in building of a IN or NOT IN sql request '.$file['relativename'].' - Bad.');
|
||||
$this->assertTrue($ok, 'Found non sanitized string in building of a IN or NOT IN sql request '.$file['relativename'].' - Bad. Lines:'.implode(',', $lines));
|
||||
//exit;
|
||||
|
||||
// Test that output of $_SERVER\[\'QUERY_STRING\'\] is escaped.
|
||||
@@ -915,4 +919,36 @@ class CodingPhpTest extends CommonClassTest
|
||||
|
||||
$this->assertEquals($expected, $this->removePhpComments($source), "Comments not removed as expected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to generate a notice after determining the line number.
|
||||
*
|
||||
* The notice is generated in a way that can be picked up in CI so that a useful annotation
|
||||
* is made on the file.
|
||||
*
|
||||
* Note: if the string occurs multiple times in a file, only the first occurrence is reported
|
||||
* and it might be for the wrong line. In most cases it should be ok.
|
||||
*
|
||||
* @param string $needle The exact string to be found, no escaping needed.
|
||||
* @param string $subject The filecontents in which this string is located.
|
||||
* @param string $filename The filename that should be reported
|
||||
* @param string $errMessage The error message to report
|
||||
*
|
||||
* @return int The line that `$needle` occurs on, or 0 if not found
|
||||
*/
|
||||
public static function reportAndGetLine($needle, $subject, $filename, $errMessage)
|
||||
{
|
||||
static $already_reported = array();
|
||||
$linenbr = 0;
|
||||
if (preg_match("/^(?<lines>.*)\\Q$needle\\E/s", $subject, $linematches)) {
|
||||
$linenbr = substr_count($linematches['lines'], "\n");
|
||||
}
|
||||
|
||||
$msg = PHP_EOL."$filename:$linenbr: $errMessage".PHP_EOL;
|
||||
if (!array_key_exists($msg, $already_reported)) {
|
||||
$already_reported[$msg] = 1;
|
||||
print $msg;
|
||||
}
|
||||
return $linenbr;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user