Closed Bug 189591 Opened 22 years ago Closed 22 years ago

crashes in NS_MsgStripRE() due to multiply-linked strings library

Categories

(Core :: XPCOM, defect)

x86
Linux
defect
Not set
critical

Tracking

()

RESOLVED FIXED

People

(Reporter: blizzard, Assigned: dougt)

References

Details

(Keywords: crash)

Attachments

(1 file, 3 obsolete files)

I'm seeing crashes when opening a mailbox that doesn't already have a .msf file
in NS_MsgStripRE().

The actual code that is crashing looks something like this:

nsXPIDLCString foo;
char *bar = "something";

char *foo = foo ? foo.get() : bar;

In this case, foo hasn't been set to anything so the test should fall through to
set foo = bar.  However, the test, which the compiler casts to this bit of code:

        // overridden to make getter_Copies mechanism work
      virtual const char_type* get() const
        {
          return (mBuffer.get() != GetSharedEmptyBufferHandle())
                    ? mBuffer->DataStart()
                    : 0;
        }

Fails to return '0'.  Instead it returns the string returned in
GetSharedEmptyBufferHandle(), even though the string is empty!

The problem seems to be that since the GRE landed that we link two copes of the
string library into the binary (one directly, as a .a and the other is included
as part of libxpcom.so) you can actually end up with multiple empty buffer
handles, as used in nsXPIDLCString::GetSharedEmptyBufferHandle():

nsXPIDLCString::GetSharedEmptyBufferHandle()
  {
    static shared_buffer_handle_type* sBufferHandle = nsnull;
    static char_type null_char = char_type(0);

    if (!sBufferHandle) {
      sBufferHandle = new nsNonDestructingSharedBufferHandle<char_type>(&null_ch
ar, &null_char, 1);
      sBufferHandle->AcquireReference(); // To avoid the |Destroy|
                                         // mechanism unless threads
                                         // race to set the refcount, in
                                         // which case we'll pull the
                                         // same trick in |Destroy|.
    }
    return sBufferHandle;
  }
Flags: blocking1.3b+
can anyone else reproduce this crash?  Blizzard, have you tried a nightly build?

Maybe replacing all string usages with nsEmbedString usages in xpfe/bootstrap
will work.
Severity: normal → critical
Keywords: crash
Attached patch hacky patch (obsolete) — Splinter Review
blizzard, can you rebuild with the statics removed.  Here is a hacky patch to
test out.  Apply it to string/src. rebuild strings, xpcom, and xpfe/bootstrap

(we will also have to clean up the statics in string/obsolete)
That's going to allocate a new buffer every single time, and all strings will be
listed as empty.  That's not going to work.

Am I mis-reading that?
No, it will allocate a new buffer every time and break the null-ness of
nsXPIDL[C]String.
I meant "all of the new allocated strings returned will be empty."  Sorry.  Yes,
it obviously breaks the nullness of the operator in question.
i am not proposing that we check this in... I was hoping that it would work well
enough to prove that the multiple statics are the problem.
That would only make the problem caused by multiple statics worse, since we'd
have one for every call instead of just 2.
duh...  what was I thinking..  What we need is two version of the string libs,
one that declares this stuff, and another that externs is.  thoughts?
jag - is there any clean way to remove the static usages from mozilla/string?
the only other thing that I can think of is to ensure that the mozilla
application does not export any of the string symbols.  Right now, I am sure
that we just dump everything to the global sym table.  
blizzard, can you try this:

drepper: DougT: Well, run moz with LD_DEBUG=reloc,symbols
LD_DEBUG_OUTPUT=<somefile> in the environment
drepper: this will produce an output file file which illustrates the lookup process
blizzard, how exactly do you start mozilla?  do you pass something on the
command line?
drepper DougT: if there is any chance that a string created by the DSO's code is
used in the app or vice versa you lose
drepper DougT: using statics this way is bad design

I think that we agree.  the static here are causing the problem.  We either need
to stop using these string classes in xpfe/bootstrap, or stop using the static
variables.

Jag, is it possible to remove the static variables?
My theory:

you pass a string which was created in a DSO with it's own string implementation
to a function in the application (which has a separate implementation) or vice
versa.

The result: the test for equality with sBufferHandle will fail even if the
string is empty.  This leads to get() returning 0.

Solution: remove the static.  Use a different way to handle empty strings.
I've got a debug log but it's frigging _huge_.  Do you want me to filter out
certain parts?
I don't think I need the debug log.  As I said in comment #14 the problem is
probably passing a string created in the apps to the DSO or vice versa.
just to clarify, i never saw this crash on windows.  that is why I thought it
might be a platform specific bug.  

bliz, are you passing anything special on the command line?
I realized a workaround in the string code would be to check the kIsImmutable
flag in the buffer handle instead of checking against the common shared buffer
handle.  This would have the disadvantage that assigning from an empty
nsSharableString to an nsXPIDLString would make the latter null.  (However, we
already have that problem between two |nsXPIDLString|s.)  An alternative would
be for |nsXPIDL[C]String| to set the kIsNULL flag on its buffer handle and
respect the kIsNULL flag in its .get().  I don't think that's quite the intent
of the kIsNULL flag (it's more for the DOM), but that might be the more sensible
solution.

jag?  scc?  thoughts?
Attached patch string patch that won't compile (obsolete) — Splinter Review
This is what I was thinking, but getting it to compile would involve major
changes in what's public and what's not or putting things we don't want in base
classes up in base classes.
I'm passing -mail on the command line.
dbaron - what about the other statics in the string code?
I don't think we use any of the others for comparisons like this.
dbaron - what needs to be public that isn't?  
Blocks: gre
Attached patch string patch that compiles (obsolete) — Splinter Review
this is dbaron's patch.  i basically converted kIsNULL to the value defined in
the class (0x80000000).
Attachment #111924 - Attachment is obsolete: true
Attachment #112022 - Attachment is obsolete: true
This fixes my crash (yay!) but I'm not a huge fan of magic constants (boo.)
regarding the magic constants - this value is defined by the
nsSharedBufferHandle class (see nsBufferHandle.h).  This enum is protected and
therefore isn't accessable outside of the nsSharedBufferHandle (or its derived
classes).  I hope there is a cleaner way to do this.  dbaron, any ideas?

Attachment #112161 - Attachment is obsolete: true
Comment on attachment 112194 [details] [diff] [review]
with dbaron's suggestions

sr=dbaron  (I'm not quite sure why
GetImplementationFlags/SetImplementationFlags were public while the flags were
private.  Perhaps I'd prefer going the other direction, but this seems OK.)
Attachment #112194 - Flags: superreview+
fix checked in:

Checking in public/nsBufferHandle.h;
/cvsroot/mozilla/string/public/nsBufferHandle.h,v  <--  nsBufferHandle.h
new revision: 1.24; previous revision: 1.23
done
Checking in public/nsXPIDLString.h;
/cvsroot/mozilla/string/public/nsXPIDLString.h,v  <--  nsXPIDLString.h
new revision: 1.7; previous revision: 1.6
done
Checking in src/nsXPIDLString.cpp;
/cvsroot/mozilla/string/src/nsXPIDLString.cpp,v  <--  nsXPIDLString.cpp
new revision: 1.8; previous revision: 1.7
done


class unfrozen per dbaron.
Status: NEW → RESOLVED
Closed: 22 years ago
Resolution: --- → FIXED
*** Bug 189985 has been marked as a duplicate of this bug. ***
+     
sBufferHandle->SetImplementationFlags(sBufferHandle->GetImplementationFlags() &
shared_buffer_handle_type::kIsNULL);


Shouldn't that be '|' instead instead of '&'?
Yes.  Eek.  Could you check that in?
Checking in nsXPIDLString.cpp;
/cvsroot/mozilla/string/src/nsXPIDLString.cpp,v  <--  nsXPIDLString.cpp
new revision: 1.9; previous revision: 1.8
done


fixed.
*** Bug 190277 has been marked as a duplicate of this bug. ***
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: