使用plphp - 如何将填充的十六进制输出写入PostgreSQL中的bytea列

时间:2011-11-09 05:56:46

标签: php postgresql

尝试将12字节字符串写入PostgreSQL

我们的代码计算一个$ number。我们不想将其转换为十六进制,用零填充它并将其写入PostgreSQL bytea字段。容易,对吧?

(作为示例)希望它返回:\ x000000002257('\ x'+ 12 bytes) 即,数字8791的左填充HEX表示:

$number = 8791;

$hexnumber = str_pad(dechex($number), 12, '0', STR_PAD_LEFT);
$packed_hex = pack('h*', $hexnumber);

// BOTH of below produce:  000000002257
pg_raise('notice', "hexnumber:         ".$hexnumber);

无法获取这些查询的任何来更新bytea,如我所愿。救命啊!

//$query = ("UPDATE blobtest SET destfile = '".$hexnumber."' WHERE pkey = ".$args[0]);

// $query = ("UPDATE blobtest SET destfile = '000000002257' WHERE pkey = ".$args[0]);
// Above produces:  \x303030303030303032323537
// (makes sense; it's quoted as a string)

// $query = ("UPDATE blobtest SET destfile = 000000002257 WHERE pkey = ".$args[0]);
// Above produces: ERROR:  column "destfile" is of type bytea but expression is of type integer

// $query = ("UPDATE blobtest SET destfile = '8791' WHERE pkey = ".$args[0]);
// Above produces:  \x38373931  as expected...

/ $query = ("UPDATE blobtest SET destfile = 8791 WHERE pkey = ".$args[0]);
// Above produces: ERROR:  column "destfile" is of type bytea but expression is of type integer

// $query = ("UPDATE blobtest SET destfile = '"."'".$packed_hex."'"."' WHERE pkey = ".$args[0]);
// Above produces:  \x only...

$query = ("UPDATE blobtest SET destfile = "."'".$packed_hex."'"." WHERE pkey = ".$args[0]);
// unterminated quoted string at or near "'"

1 个答案:

答案 0 :(得分:1)

您似乎忘记了bytea文字的前导\x。如果$packed_hex包含000000002257,您可以写:

$query = ("UPDATE blobtest SET destfile = '\x".$packed_hex."' WHERE pkey = ".$args[0]);

你需要在PostgreSQL 9.0及更低版本(IIRC)上SET bytea_output = 'hex'以十六进制形式返回bytea而不是icky旧的八进制转义格式。较新版本默认为hex

SQL注入

<soapbox>您的代码显示了一个坏习惯。使用参数化查询来避免SQL注入。您的应用目前可能会生成packed_hex,但是谁知道以后如何重用此代码。始终使用参数化查询以避免SQL injection。请参阅the PHP manual on SQL injection</soapbox>

正如所写,你的代码是可悲的,非常不安全。想象一下,如果$args[0]包含来自恶意用户的NULL);DROP SCHEMA public;--。你刚刚发送了:

UPDATE blobtest SET destfile = '\000000002257' WHERE pkey = 0);DROP SCHEMA public;--);

到你的数据库,它执行了什么都没做的UPDATE,然后是一个很可能会破坏你的数据库的DROP SCHEMA public;,然后是一个忽略其余数据的注释。哎呀,splat,你的数据库,bobby tables再次罢工。

这样写得更好:

$stm = pg_prepare($connection, "", "UPDATE blobtest SET destfile = $1 WHERE pkey = $2");
$result = pg_execute($connection, "", array($packed_hex, $args[0]));