develooper Front page | perl.perl5.porters | Postings from September 2010

[perl #77810] Scalars vs globs

Thread Previous
From:
Father Chrysostomos
Date:
September 12, 2010 12:29
Subject:
[perl #77810] Scalars vs globs
Message ID:
rt-3.6.HEAD-5116-1284319760-1492.77810-75-0@perl.org
# New Ticket Created by  Father Chrysostomos 
# Please include the string:  [perl #77810]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=77810 >


There are various bugs in perl related to the fact that globs are scalars.

Various Perl operators need to distinguish between globs and scalars, even though the former are a subset of the latter.

Now, there are two types of globs: autovivified globs (I call these ‘real globs’) and copies of globs (fake globs or glob copies).

The first kind, a real glob, is what you get when you write *foo (prior stash manipulation aside). A real glob is always a glob. That sv is never downgraded to anything else. Even passing it to undef does not undefine it, but only its contents.

The second occurs when you write ‘$a = *foo’. These are marked with the SVf_FAKE flag. I think the original purpose of the distinction was to allow $a to be assigned something other than a glob after it had been assigned a glob.

Now different operators make the distinction between globs and scalar in different ways. For example, the = operator (in 5.12 and earlier) or, rather, sv_setsv_flags treats only real globs on the LHS as globs. Fake globs are scalars.

Other operators, such as tie(d), untie and *{}, treat any glob as a glob, and not as a scalar.

Now the *{} dereference operator returns its operand if it sees it as a glob.

This means that
• *$glob_copy = [] is the same as $glob_copy = []
• tie *$glob_copy  is the same as tie $glob_copy
• untie $scalar doesn::t work if the last thing assigned was a glob.

(The first of those three examples is fixed in blead with a workaround for the actual problem. We now treat *{...}= as a special kind of assignment operator. List assignment is still broken.)

If the patch for #77362 (glob-to-lvalue assignment) is applied, then there will be this problem, too:

 (*$pvlv_glob) = [];

This innocent-looking statement will start assigning [] to $pvlv_glob, instead of the array slot of the GP. (Currently globs are stringified when assigned to PVLVs.)

Now the real problem here seems to be that *{} is returning glob copies. We could make this operator return GvEGV(sv) in the presence of the SVf_FAKE flag, and make all operators that need to distinguish between globs and scalars check the SVf_FAKE flag.

This would fix all these bugs in one fell swoop:
• 77496 tied $tie when $tie holds a glob
• 77502 *{\$tie} when $tie holds a glob
• 77508 (*$glob_copy) = ...
• 77688 tie $glob_copy
• The untie case mentioned above
• 71686 globs can be un-globbed (fixed; but the fix can be reverted, simplifying the code)
• 1804 *$glob_copy = ... (likewise fixed)
• part of 77684 (opening \*$glob_copy)
And the changes to tie_fetch_count.t in the patch for 77598 will be unnecessary.

(You can consider this a meta-ticket for all those.)

(Some of those would actually still need fixing, but the fix would be to check a single flag, instead of the more complex, more intrusive patches already in some of those tickets.)

There are two problems that can result:

• Putting a fake glob in the symbol table will have the following effect:

  $::{foo} = *bar; # *foo is now fake
  *foo = $baz; # aliases both *foo AND *bar to *baz.

This can be solved easily by making *{} turn the fake flag off if it is doing a symbolic dereference (or the compile-time equivalent). Having fake globs in the symbol table is questionable anyway.

• This code:

  $foo_copy = *foo;
  *$foo_copy = *bar;

will make *foo (aka GvEGV($foo_copy)) a copy of *bar, instead of making $foo_copy a copy of *bar.

This is the most serious problem.

The only solution I can think of so far is to return some sort of magical variable that will delegate assignment to the fake glob, turning off its fake flag temporarily during the assignment. So we will be back to hacks upon hacks, but at least this hack will solve *all* the bugs above, allowing two existing hacks in blead to be removed.

This will change the meaning of \*$glob_copy, making it similar to \*$io. I think that’s a good thing.

---
Flags:
    category=core
    severity=medium
---
Site configuration information for perl 5.13.4:

Configured by sprout at Sun Sep  5 17:19:23 PDT 2010.

Summary of my perl5 (revision 5 version 13 subversion 4 patch v5.13.4-144-gf1dcae2) configuration:
  Snapshot of: f1dcae2ca2c256c755eeec79c4e7d4d5b9cf658f
  Platform:
    osname=darwin, osvers=10.4.0, archname=darwin-ld-2level
    uname='darwin pint.local 10.4.0 darwin kernel version 10.4.0: fri apr 23 18:28:53 pdt 2010; root:xnu-1504.7.4~1release_i386 i386 '
    config_args='-Dusedevel -des -Ui_db -Uuseithreads -Duselongdouble'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=define
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
    optimize='-O3',
    cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.2.1 (Apple Inc. build 5664)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=4, nvtype='long double', nvsize=16, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib
    libs=-ldbm -ldl -lm -lutil -lc
    perllibs=-ldl -lm -lutil -lc
    libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches:
    

---
@INC for perl 5.13.4:
    /usr/local/lib/perl5/site_perl/5.13.4/darwin-ld-2level
    /usr/local/lib/perl5/site_perl/5.13.4
    /usr/local/lib/perl5/5.13.4/darwin-ld-2level
    /usr/local/lib/perl5/5.13.4
    /usr/local/lib/perl5/site_perl
    .

---
Environment for perl 5.13.4:
    DYLD_LIBRARY_PATH (unset)
    HOME=/Users/sprout
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash


Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About