Pg: Be more strict with boolean bind parameters

Reason for this is that, with FU::SQL, it's possible to accidentally
introduce a bind parameter when a WHERE clause was intended (i.e.
"WHERE $1"). That's pretty bad, but can easily be caught by simply not
accepting *every* possible value as boolean.
This commit is contained in:
Yorhel 2025-06-12 16:45:07 +02:00
parent 02b1dcc328
commit a7868f74bf
3 changed files with 26 additions and 8 deletions

View file

@ -631,10 +631,12 @@ Some built-in types deserve a few additional notes:
=item bool =item bool
Boolean values are converted to C<builtin::true> and C<builtin::false>. As bind Boolean values are converted to C<builtin::true> and C<builtin::false>.
parameters, Perl's idea of truthiness is used: C<0>, C<false> and C<""> are
false, everything else is true. Objects that overload I<bool> are also As bind parameters, values recognized by C<to_bool()> in L<FU::Util> are
supported. C<undef> always converts to SQL C<NULL>. accepted, in addition to C<0>, C<"f"> and C<""> for false and C<1>, and C<"t">
for true. C<undef> always converts to SQL C<NULL>. Everything else throws an
error.
=item bytea =item bytea

View file

@ -82,8 +82,15 @@ RECVFN(bool) {
} }
SENDFN(bool) { SENDFN(bool) {
int r = fu_2bool(aTHX_ val); /* So that we also recognize \0 and \1 */ int r = fu_2bool(aTHX_ val);
fustr_write_ch(out, r < 0 ? SvTRUE(val) : r); if (r < 0) {
STRLEN l;
const char *x = SvPV(val, l);
if (l == 0 || (l == 1 && (*x == '0' || *x == 'f'))) r = 0;
else if (l == 1 && (*x == '1' || *x == 't')) r = 1;
else SERR("invalid boolean value: %s", x);
}
fustr_write_ch(out, r);
} }
RECVFN(void) { RECVFN(void) {

View file

@ -61,8 +61,17 @@ sub f($type, $p_in) {
$array->[0] = 0; $array->[0] = 0;
} }
v bool => true, undef, 1, 't'; v bool => true, true, 1, 't';
v bool => false, undef, 0, 'f'; v bool => \1, true, 1, 't';
v bool => 1, true, 1, 't';
v bool => 't', true, 1, 't';
v bool => false, false, 0, 'f';
v bool => \0, false, 0, 'f';
v bool => 0, false, 0, 'f';
v bool => '', false, 0, 'f';
v bool => 'f', false, 0, 'f';
f bool => 2;
f bool => [];
v int2 => $_ for (1, -1, -32768, 32767, '12345', -12345, 123.0); v int2 => $_ for (1, -1, -32768, 32767, '12345', -12345, 123.0);
f int2 => $_ for (-32769, 32768, [], '', 'a', 1.5); f int2 => $_ for (-32769, 32768, [], '', 'a', 1.5);