perl11 / cperl

A perl5 with classes, types, compilable, company friendly, security
http://perl11.org/
Other
142 stars 17 forks source link

signature return value in list aligned #395

Closed AlexBurnes closed 5 years ago

AlexBurnes commented 5 years ago

Return value for variable in list from signature function is wrong aligned by 8 bits left

The code was taken from an asn1 decoder library, the code in both functions are the same except the way function arguments are initiated:

use strict;
my $buf = pack("CCC",0x5f,0x81,0x3a);

my ($pos, $etag, $id) = decode_tl(0, $buf);
printf unpack("H*", $etag)." id => $id\n";

my ($pos, $etag, $id) = decode_tl_signature(0, $buf);
printf unpack("H*", $etag)." id => $id";

$id >>=8;
printf ", shifted id => $id\n";

sub decode_tl {
    my ($pos) = @_;

    my $etag = substr($_[-1], $pos++, 1);

    my $tag = ord($etag);
    my $id = $tag & 0x1f;

    if($id == 0x1f) {
        my $b;
        my $n=1;
        $id = 0;
        do {
            $tag = substr($_[-1], $pos++, 1);
            $etag .= $tag;
            $b = ord substr($tag,-1);
            $id = ($id << 7) + ($b & 0x7f);
        }
        while($b & 0x80);
    }

    return ($pos, $etag, $id);
}

sub decode_tl_signature ($pos, \$buf) {

    my $etag = substr($buf, $pos++, 1);

    my $tag = ord($etag);
    my $id = $tag & 0x1f;

    if($id == 0x1f) {
        my $b;
        my $n=1;
        $id = 0;
        do {
            $tag = substr($buf, $pos++, 1);
            $etag .= $tag;
            $b = ord substr($tag,-1);
            $id = ($id << 7) + ($b & 0x7f);
        }
        while($b & 0x80);
    }

    return ($pos, $etag, $id);
}

/opt/cperl-5.28.2/bin/cperl ./test_signature.pl 5f813a id => 186 5f813a id => 47616, shifted id => 186

The same for cperl 5.24.4, 5.26.5. Perl 5.26.1 has no issue. If variable $etag remove from return list than value in variable id is ok.

rurban commented 5 years ago

With DEBUGGING at least I get a proper crash. Looking at it. Nice test case, thanks! The problem is that the \$buf arg is freed in leavesub, leave_scope, and not properly assigned back to the original value as planned.

rurban commented 5 years ago

Fixed with 5.30.0c, thanks for the nice test case.