Loading ...
Sorry, an error occurred while loading the content.

Possible bug in SOAP::Lite

Expand Messages
  • Vishal Verma
    Hi there, What follows is the description of what I think is a bug in SOAP::Lite. It s not a major bug, but may cause you a lot of grief, as it did to me. The
    Message 1 of 4 , May 4, 2003
    • 0 Attachment
      Hi there,

      What follows is the description of what I think is a
      bug in SOAP::Lite. It's not a major bug, but may cause
      you a lot of grief, as it did to me.

      The function find_target() in Lite.pm, checks if the
      symbol table for a particular package exists or not,
      before it loads the module using a "require"
      statement. Now, the checking the existence of a symbol
      table is not a confirmatory test of whether a module
      has already been loaded or not. Consider the following
      package, for example:

      package A;

      # this sub never gets called
      sub never_call_me
      {
      B::foo();
      }


      Let's suppose that the SOAP server has both packages A
      and B specified in dispatch_to list. Now if a request
      arrives for a function in package A, Perl will parse
      package A and when it parses sub "never_call_me", it
      will create the symbol table for B and an empty entry
      for B::foo. So at this point, the symbol table for B
      exists, but B hasn't been loaded. Now a request for
      "foo" in B arrives. It will error out saying "unable
      to find function foo in package B". The reason being
      that B was never loaded using a "require B" statement.

      The right way to check if a package has been loaded or
      not is to check if an entry for the module in %INC
      hash. But before you do that, you'll have to translate
      the colons in the module name to slashes. Here's the
      patch for the latest version 0.55. You should execute
      this patch in the SOAP-Lite-0.55 directory as
      patch -p0 < patchfile

      The contents of patchfile:

      --- lib/SOAP/Lite.pm Mon Apr 15 21:42:48 2002
      +++ lib/SOAP/Lite.pm Fri May 2 17:20:40 2003
      @@ -2116,7 +2116,9 @@
      }

      no strict 'refs';
      - unless (defined %{"${class}::"}) {
      + my $class_inc_entry = $class;
      + $class_inc_entry =~ s#::#/#og;
      + unless (defined $INC{$class_inc_entry}) {
      # allow all for static and only specified path
      for dynamic bindings
      local @INC = (($static ? @INC : ()), grep {!ref
      && m![/\\.]!} $self->dispatch_to);
      eval 'local $^W; ' . "require $class";


      If you think I'm missing something, let me know. As
      such, I don't know about Perl that much.

      -vish


      __________________________________
      Do you Yahoo!?
      The New Yahoo! Search - Faster. Easier. Bingo.
      http://search.yahoo.com
    • Duncan Cameron
      ... A couple of points. A package might have been loaded due to it being within the same file as another package. For example; file A.pm package A; package
      Message 2 of 4 , May 5, 2003
      • 0 Attachment
        On 2003-05-04 Vishal Verma wrote:
        >Hi there,
        >
        >What follows is the description of what I think is a
        >bug in SOAP::Lite. It's not a major bug, but may cause
        >you a lot of grief, as it did to me.
        >
        >The function find_target() in Lite.pm, checks if the
        >symbol table for a particular package exists or not,
        >before it loads the module using a "require"
        >statement. Now, the checking the existence of a symbol
        >table is not a confirmatory test of whether a module
        >has already been loaded or not. Consider the following
        >package, for example:
        >
        >package A;
        >
        ># this sub never gets called
        >sub never_call_me
        >{
        > B::foo();
        >}
        >
        >
        >Let's suppose that the SOAP server has both packages A
        >and B specified in dispatch_to list. Now if a request
        >arrives for a function in package A, Perl will parse
        >package A and when it parses sub "never_call_me", it
        >will create the symbol table for B and an empty entry
        >for B::foo. So at this point, the symbol table for B
        >exists, but B hasn't been loaded. Now a request for
        >"foo" in B arrives. It will error out saying "unable
        >to find function foo in package B". The reason being
        >that B was never loaded using a "require B" statement.
        >
        >The right way to check if a package has been loaded or
        >not is to check if an entry for the module in %INC
        >hash. But before you do that, you'll have to translate
        >the colons in the module name to slashes. Here's the
        >patch for the latest version 0.55. You should execute
        >this patch in the SOAP-Lite-0.55 directory as
        >patch -p0 < patchfile
        >
        >The contents of patchfile:
        >
        >--- lib/SOAP/Lite.pm Mon Apr 15 21:42:48 2002
        >+++ lib/SOAP/Lite.pm Fri May 2 17:20:40 2003
        >@@ -2116,7 +2116,9 @@
        > }
        >
        > no strict 'refs';
        >- unless (defined %{"${class}::"}) {
        >+ my $class_inc_entry = $class;
        >+ $class_inc_entry =~ s#::#/#og;
        >+ unless (defined $INC{$class_inc_entry}) {
        > # allow all for static and only specified path
        >for dynamic bindings
        > local @INC = (($static ? @INC : ()), grep {!ref
        >&& m![/\\.]!} $self->dispatch_to);
        > eval 'local $^W; ' . "require $class";
        >
        >
        >If you think I'm missing something, let me know. As
        >such, I don't know about Perl that much.
        >
        A couple of points.
        A package might have been loaded due to it being within the same file as
        another package. For example;

        file A.pm

        package A;

        package A::SubPackageA;

        1;

        Odd perhaps, but still valid. In this case you definitely don't want to
        do a 'require A::SubPackageA;'. So checking %INC isn't quite the right
        thing to do.

        In your case,

        sub never_call_me
        {
        B::foo();
        }

        shouldn't you have a 'use B;' statement anyway.

        Regards,
        Duncan
      • Vishal Verma
        ... I have a question. Does it hurt to do a require A::SubPackageA , if A::SubPackageA has already been loaded? What side effects will that have? ...
        Message 3 of 4 , May 7, 2003
        • 0 Attachment
          --- Duncan Cameron <dcameron@...> wrote:
          > A couple of points.
          > A package might have been loaded due to it being
          > within the same file as
          > another package. For example;
          >
          > file A.pm
          >
          > package A;
          >
          > package A::SubPackageA;
          >
          > 1;
          >
          > Odd perhaps, but still valid. In this case you
          > definitely don't want to
          > do a 'require A::SubPackageA;'. So checking %INC
          > isn't quite the right
          > thing to do.

          I have a question. Does it hurt to do a "require
          A::SubPackageA", if "A::SubPackageA" has already been
          loaded? What side effects will that have?

          >
          > In your case,
          >
          > sub never_call_me
          > {
          > B::foo();
          > }
          >
          > shouldn't you have a 'use B;' statement anyway.

          Remember, I told you that nobody calls
          "never_call_me". So we don't actually need a "use B;"
          statement for this to work. Odd perhaps, but still
          valid. I actually saw this happen!


          -vish

          __________________________________
          Do you Yahoo!?
          The New Yahoo! Search - Faster. Easier. Bingo.
          http://search.yahoo.com
        • Duncan Cameron
          ... Well in this case the require will fail because there is no such file as A/SubPackageA.pm. But in general you are right, there should be no problem in
          Message 4 of 4 , May 7, 2003
          • 0 Attachment
            On 2003-05-07 Vishal Verma wrote:
            >--- Duncan Cameron <dcameron@...> wrote:
            >> A couple of points.
            >> A package might have been loaded due to it being
            >> within the same file as
            >> another package. For example;
            >>
            >> file A.pm
            >>
            >> package A;
            >>
            >> package A::SubPackageA;
            >>
            >> 1;
            >>
            >> Odd perhaps, but still valid. In this case you
            >> definitely don't want to
            >> do a 'require A::SubPackageA;'. So checking %INC
            >> isn't quite the right
            >> thing to do.
            >
            >I have a question. Does it hurt to do a "require
            >A::SubPackageA", if "A::SubPackageA" has already been
            >loaded? What side effects will that have?
            Well in this case the 'require' will fail because there is no such file
            as A/SubPackageA.pm. But in general you are right, there should be no
            problem in requiring a file that has already been loaded (if I read
            perlfunc correctly!).
            Given this, I am not too sure what SOAP::Lite is really checking for
            when it tests the existence of the symbol table for, in your example,
            module B.

            Regards,
            Duncan
          Your message has been successfully submitted and would be delivered to recipients shortly.