patjoly / geo-gpx

Perl module to create and parse GPX files
0 stars 1 forks source link

Error "can't open file GLOB(...)" #4

Closed sebastic closed 1 year ago

sebastic commented 1 year ago

As reported in Debian Bug #1056346 by @alexishuxley:

According to the man page, Geo::Gpx's new() method can be passed a file name or an already-opened file handle, but when passed a filehandle it can fail to detect that it is a filehandle and attempts to treat it like a file to be opened.

Here's a recipe to demonstrate the bug:

#  Create a minimal stupid GPX file
echo -e '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<gpx version="1.1">\n</gpx>' > test.gpx
#  cat it via pipe into a minimal Geo::Gpx script
cat test.gpx | perl -e 'use Geo::Gpx; Geo::Gpx->new(input => \*STDIN);'
#  same but not via a pipe
perl -e 'use Geo::Gpx; Geo::Gpx->new(input => \*STDIN);' < test.gpx

On Debian 11 (libgeo-gpx-perl 0.26-5) the right thing happens:

tortelli$ echo -e '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<gpx version="1.1">\n</gpx>' > test.gpx
tortelli$ cat test.gpx | perl -e 'use Geo::Gpx; Geo::Gpx->new(input => \*STDIN);'
tortelli$ perl -e 'use Geo::Gpx; Geo::Gpx->new(input => \*STDIN);' < test.gpx
tortelli$

On Debian 12 (libgeo-gpx-perl 1.09-1) the wrong thing happens:

farfalle$ echo -e '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<gpx version="1.1">\n</gpx>' > test.gpx
farfalle$ cat test.gpx | perl -e 'use Geo::Gpx; Geo::Gpx->new(input => \*STDIN);'
farfalle$ perl -e 'use Geo::Gpx; Geo::Gpx->new(input => \*STDIN);' < test.gpx
Uncaught exception from user code:
      can't open file GLOB(0x5648fd6bd630) No such file or directory at /usr/share/perl5/Geo/Gpx.pm line 155.
      Geo::Gpx::new("Geo::Gpx", "input", GLOB(0x5648fd6bd630)) called at -e line 1
farfalle$

As far as the user is concerned, 'cat blah |' and '< blah' are both facilitating some command to read an already-opened file from stdin. /usr/share/perl5/Geo/Gpx.pm:155 is using '(-f ...)' to determine if the thing needs opening, but '(-f ...)' is not suitable for this! It is only suitable for determining whether its operand is or was opened from a file. Here's a demo with pure Perl:

farfalle$ perl -e 'printf "%d\n", (-f \*STDIN);' < /etc/passwd
1
farfalle$ cat /etc/passwd | perl -e 'printf "%d\n", (-f \*STDIN);'
0
farfalle$

Debian 11 and 12 show exactly the same output from these commands. In both commands the file /etc/passwd is already open as far as perl is concerned. But the difference in output (1 or 0) illustrates that using '(-f ...)' is not a good test for whether something needs opening.

I note that Debian 11's libgeo-gpx-perl's /usr/share/perl5/Geo/Gpx.pm does not use '(-f ...)'.