jmClifford has asked for the wisdom of the Perl Monks concerning the following question:

Hi. I have a pm module that has been working find till now. However recently with structuring the code I now get the following message (last item of console output);

Console output -------------- cmd; AT @2 x x AT_@2 Cmd; AT @2 Length; 15 Response; 0123456789AB__>. cmd; 01 00 x x PIDs01_20 Cmd; 01 00 Length; 21 Response; 41 00 BE 1F B8 11 __>. cmd; 01 20 x x PIDs21_40 Cmd; 01 20 Length; 21 Response; 41 20 80 06 00 11 __>. cmd; 01 40 x x PIDs41_60 Cmd; 01 40 Length; 21 Response; 41 40 78 D0 00 00 __>. TPA $cmd; 0101 cmd; 0101 xWin32::API::Call: parameter 2 had a buffer overflow at C:/S +trawberry/perl/vendor/lib/Win32API/CommPort.pm line 217.

The last bit indicates a buffer overflow, despite the fact that the serial port (Com5) has worked quite well up to that point. The Win32::SerialPort is packed in my own pm module which is presented below;

Serial.pm ---------- #!usr/bin/perl use strict; use warnings; use Win32::SerialPort; my $port; package Serial; require Exporter; Exporter->import('import'); #Now declare what we permit to be visible within the module. our @EXPORT = qw( &Serial_Init &Serial_TrxRcv &Serial_Close); use Time::HiRes qw(usleep); # ############ subroutine Serial_Init ################################ +################### sub Serial_Init { my $port_name = 'COM5'; #my $config_file = 'setup.cfg'; # use this to configure from th +e file $port = new Win32::SerialPort( $port_name ) || die "Unable to open: $^E\n"; # $^E EXTENDED +_OS_ERROR #$port = new Win32::SerialPort($port_name, $config_file) || die "U +nable to open: $^E\n"; $port->handshake('none'); # none dtr rts xoff $port->baudrate(38400); # 19200 57600 1200 9600 115200 4800 +600 2400 300 38400 $port->parity('none'); # space none odd even mark #$port->parity_enable(1); # for any parity except "none +" $port->databits(8); # options 7 8 $port->stopbits(1); # options 2 1 $port->buffers(256, 256); $port->read_interval(0); #RI $port->read_const_time(20); #RC $port->write_char_time(1); #WM $port->write_const_time(100); #WC print "Write settings; "; $port->write_settings || undef $port; # A report out to the console my $baud = $port->baudrate; my $parity = $port->parity; my $data = $port->databits; my $stop = $port->stopbits; my $hshake = $port->handshake; print "B = $baud, D = $data, S = $stop, P = $parity, H = $hshake\n +\n"; # use the below to save the current configuration # if ( $port ) { $port->save('setup.cfg') ; print "Serial Port OK +\n" }; } # ############## subroutine Serial_TrxRcv ############### sub Serial_TrxRcv { my ($cmd) = @_; my $response = ""; print "cmd; $cmd x"; $port->write($cmd."\r"); # IT CRASHES HERE !!!!!!! print " x\n"; my $loop = 1; while( $loop ) { usleep(200000); # 0.2 of a second my $partial_resp; $partial_resp = $port->input; # chomp $partial_resp; # only removes linefeeds $response = $response.$partial_resp; # print $response; #my $responseHex = unpack ('H*', $response); #print $responseHex."\n"; my $last = substr ( $response, -1 ); # get the last charact +er if ($last eq ">") { $loop = 0; # $response = substr( $response, 0, -1); + # -1 removes the ">"; #Leave the ">" character # chomp $response; # only removes lin +efeeds next; } print "."; } return $response; } # ############## subroutine Serial_Close ################# sub Serial_Close { $port->close(); } # ############## Execute when module exits ############## END { undef $port; # free it before global destruction runs } 1;

On doing a subroutine call Serial_TrxRcv it crashes here where indicated (with "IT CRASHES HERE !!!!!"). This is after many uses of the subroutine. This is easily correlated with the console output (presented). What is my issue ? Do I need to clear the buffer ?

Regards JC.....

Replies are listed 'Best First'.
Re: Win32::SerialPort, buffer overflow
by stevieb (Canon) on Nov 09, 2024 at 09:15 UTC

    Technically, the following is incorrect:

    #Now declare what we permit to be visible within the module.

    Putting things in @EXPORT or @EXPORT_OK doesn't mean that those elements are 'visible', it means that they can be imported by the user of the library. @EXPORT means that those subroutines are imported by the calling script automatically when they use your module, and @EXPORT_OK means the caller has to import them explicitly. It is always advisable to allow a caller to choose what they want to import (ie. best always to use @EXPORT_OK).

    Also, here:

    our @EXPORT = qw( &Serial_Init &Serial_TrxRcv &Serial_Close);

    ... you don't need the ampersands (ie. '&').

Re: Win32::SerialPort, buffer overflow
by stevieb (Canon) on Nov 09, 2024 at 08:54 UTC
    However recently with structuring the code I now get the following message

    Without reading anything beyond that sentence, the logical question is what did you restructure? Did you keep track of your changes?

      It definitely looks like there's a discrepancy on output, but it doesn't appear you've shown how you call Serial_TrxRcv() or with what data. There's no way to know what the problem is without that information.

        Hi. Thank you for your replys. I think I can be now more specific about my issue of the buffer overflow error. The routine I call for COM5 serial handshaking is Serial_TrxRcv( $commandForTransmission ). In my main routine I have a sub doing this which is below;

        sub ProcessPIDs { # print "Inside ProcessPIDs \n"; # Process the input arguments my ( $nickname, $ref_nicknametocommand ) = @_; my %InSubNickNameToCommand = %{$ref_nicknametocommand}; # De-ref +erence the reference to a hash my $ccmd; $ccmd = $InSubNickNameToCommand{ $nickname }; # ne +ed further ERROR checking here !!!!!! my $newcmd = '0101'; print "\$ccmd; $ccmd ".length($ccmd). " \$newcmd; $newcmd ".le +ngth($newcmd)."\n"; # my $newcmd = $ccmd; # not work my $response = Serial_TrxRcv($newcmd); my $result; ...etc...

        If I use Serial_TrxRcv in the manner as above, I do not have error. If I call the same but with the parameter $ccmd then I get the error. This $ccmd is initialised from a hash structure. The hash is to provide quick mapping from a nickname to the wanted command string. I provide a comparison between these 2 parameters with the just above programs and the console output below;

        TPA $ccmd; 0101 4 $newcmd; 0101 4 cmd; 0101 x x MonStatus Cmd; 0101 Length; 21 Response; 41 01 00 07 61 00 __>. $nickname MonStatus; 00 07 61 00 TPB

        The non-faulty and faulty parameters both appear the same and have the same lengths. So, do people have any further ideas about my problem ??

        Thanks. Regards JC.....