| From | Sent On | Attachments |
|---|---|---|
| madd...@free.fr | Aug 4, 2011 5:53 am | |
| Nicholas Clark | Aug 4, 2011 6:09 am | |
| madd...@free.fr | Aug 4, 2011 6:44 am | |
| Sébastien Aperghis-Tramoni | Aug 4, 2011 8:38 am | |
| Dave Mitchell | Aug 5, 2011 2:56 am | |
| Nicholas Clark | Aug 8, 2011 3:11 am | |
| Sébastien Aperghis-Tramoni | Aug 8, 2011 3:21 pm | |
| Jan Dubois | Aug 8, 2011 4:04 pm | |
| Dave Mitchell | Aug 11, 2011 1:37 am | |
| Chas. Owens | Aug 11, 2011 8:31 am | |
| Jesse Luehrs | Aug 11, 2011 8:40 am | |
| Chas. Owens | Aug 11, 2011 11:34 am | |
| Jan Dubois | Aug 11, 2011 12:24 pm | |
| Nicholas Clark | Aug 11, 2011 12:58 pm | |
| Jan Dubois | Aug 11, 2011 3:24 pm |
| Subject: | Scalar flags pollution | |
|---|---|---|
| From: | madd...@free.fr (madd...@free.fr) | |
| Date: | Aug 4, 2011 5:53:35 am | |
| List: | org.perl.perl5-porters | |
Hello all,
I'm pretty sure this is a well-known caveat, but I don't know where to find more information about this. Maybe I'm using the wrong terms as well.
The problem can be exposed with the following example:
use strict; use Devel::Peek;
my @values = ( 42, 3.1415, "oh hai", 2.618, 56 );
for my $i (0..$#values) { my $v = $values[$i]; Dump $v; }
Let's run it:
$ perl5.14.0 bug-flags-pollution SV = IV(0x674b80) at 0x674b90 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 42
so far, so good
SV = PVNV(0x651570) at 0x674b90 REFCNT = 1 FLAGS = (PADMY,NOK,pNOK) IV = 42 NV = 3.1415 PV = 0
uh, now it has become a kind of dual-var with both IV and NV
SV = PVNV(0x651570) at 0x674b90 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) IV = 42 NV = 3.1415 PV = 0x671100 "oh hai"\0 CUR = 6 LEN = 16
and now, a triple-var, with the PV as well
SV = PVNV(0x651570) at 0x674b90 REFCNT = 1 FLAGS = (PADMY,NOK,pNOK) IV = 42 NV = 2.618 PV = 0x671100 "oh hai"\0 CUR = 6 LEN = 16
here, the new NV replaces the old one, keeping the rest untouched
SV = PVNV(0x651570) at 0x674b90 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 56 NV = 2.618 PV = 0x671100 "oh hai"\0 CUR = 6 LEN = 16
and the same for the last IV
I guess that the problem is because $v is at each loop recreated at the same memory address, with no zeroing, hence being filled with the flags and values from the previous loop.
This behaviour exists and is consistent since at least 5.6.0
With usual Perl code, in Perl land, this is usually transparent because Perl DTRT of converting between the different values to give the user the good one.
However, this flags pollution becomes a problem with XS code, or at the very least with NetSNMP::agent, the module which exposed the issue. The relevant parts of its XS code are:
/* We want an integer here */
if ((SvTYPE(value) == SVt_IV) || (SvTYPE(value) == SVt_PVMG) ||
SvIOK(value)) {
/* Good - got a real one (or a blessed object that we hope will turn
out OK) */
ltmp = SvIV(value);
/* ... */
}
else if (SvPOKp(value)) {
/* Might be OK - got a string, so try to convert it, allowing base 10,
octal, and hex forms */
/* ... */
}
else {
snmp_log(LOG_ERR, "Non-integer value passed to setValue with
ASN_INTEGER: type was %d\n",
SvTYPE(value));
/* ... */
}
If I understand correctly, this code is subtly wrong in that it doesn't take into account SVt_PVIV, which is what Perl gives it because of the flags pollution bug.
I will send a patch to Net-SNMP maintainers in order to improve this part, but this won't be of any help except in a very distant future, because I work with production versions (IOW, old and packaged). Hence this mail to see if anyone would have an idea of a workaround.
Currently, the only one I found with NetSNMP::agent is to stringify everything. A bit unstatisfaying. I would prefer to have scalars with the correct flags.
Note: I saw that writing the code this way:
for my $v (@values) { ... }
doesn't expose the issue, but it doesn't fit my need, which is the module POE::Component::NetSNMP::agent
Thanks in advance.
-- Sébastien Aperghis-Tramoni
Close the world, txEn eht nepO.





