ranguard / text-vcard

Perl package to edit and create vCard(s) (RFC 2426)
22 stars 15 forks source link

Strange race condition on parsing a file with multiple line-feed and no carriage return #62

Open sei-vsarvepalli opened 4 years ago

sei-vsarvepalli commented 4 years ago

I noticed an interesting bug in Text::Vcard::Addressbook package. When a file is provided with empty line-feeds the package reaches what looks like aa race-condition infinitely stuck. Here is the sample vcf file and script to trigger this

vi (set list mode)

BEGIN:VCARD^M$ VERSION:3.0^M$ UID:62df1a1531-0de220c1b8-2ffd3b9cee^M$ FN:Extra-IP Billing^M$ EMAIL:billing@extra-ip.net^M$ PRODID:-//Extra-IP.net//Contact Synchronizer//EN^M$ REV:2016-04-23T01:06:48Z^M$ NOTE: JDJDJDH^M$ $ $ $ $ N:Billing;Extra-IP;;;^M$ END:VCARD^M$

use Text::vCard::Addressbook;    
$address_book = Text::vCard::Addressbook->new({'source_file'  => "Default.vcf"});

vijay@socrates:~/vcard-bomb$ time perl test_vcard.pl ^C real 0m3.466s user 0m3.435s sys 0m0.028s

vijay@socrates:~/vcard-bomb$

triggers a race condition. However if I do a simple override of the "new" subroutine the race condition does not exists

use Text::vCard::Addressbook;
*Text::vCard::Addressbook::new = sub {
my ( $proto, $conf ) = @_;
my $class = ref($proto) || $proto;
my $self = {};

bless( $self, $class );

# create some where to store out individual vCard objects
$self->{'cards'} = [];
$self->{encoding_in}  = $conf->{encoding_in}  || 'UTF-8';
$self->{encoding_out} = $conf->{encoding_out} || 'UTF-8';

# slurp in file contents
if ( defined $conf->{'source_file'} ) {

    croak "Unable to read file $conf->{'source_file'}\n"
        unless -r $conf->{'source_file'};

    my $filename = $conf->{source_file};
    my $file     = $self->_path($filename);
    $conf->{source_text} = $file->slurp( $self->_iomode_in );
}
$conf->{source_text} =~s /\n+/\n/sgi;
# Process the text if we have it.
$self->_process_text( $conf->{'source_text'} )
    if defined $conf->{'source_text'};

return $self;
};
$address_book = Text::vCard::Addressbook->new({'source_file'  => "Default.vcf"});

Updated line just removes repeated line-feed using "$conf->{source_text} =~s /\n+/\n/sgi;" statement

vijay@socrates:~/vcard-bomb$ time perl test_vcard.pl real 0m0.124s user 0m0.115s sys 0m0.008s vijay@socrates:~/vcard-bomb$