Closed
Bug 297277
Opened 20 years ago
Closed 20 years ago
potential OOM crash/mlk [@ nsPrintOptions::_CreatePrintSettings]
Categories
(Core :: Printing: Output, defect)
Tracking
()
RESOLVED
FIXED
People
(Reporter: timeless, Assigned: bastiaan)
References
()
Details
(Keywords: crash, memory-leak)
Crash Data
Attachments
(2 files, 17 obsolete files)
|
77.88 KB,
patch
|
dmosedale
:
superreview+
benjamin
:
approval1.8b4+
|
Details | Diff | Splinter Review |
|
72.15 KB,
patch
|
Details | Diff | Splinter Review |
this is an audit of sorts, it's based on a dreftool audit
http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/gfx/src/nsPrintOptionsImpl.cpp&rev=1.67&mark=265#260
Deref-error: "sDefaultFont"
http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/gfx/src/nsPrintOptionsImpl.cpp&rev=1.67&mark=887#882
Deref-error: "printSettings"
and this is really a followup to bug 235643 ...
bonus points for replacing SetLength(0) with Truncate()
partial credit for fixing indentation to not have 3 space (code seems to be a
mix of 1space, 2space, 3space, 4space, plus combinations)
| Assignee | ||
Comment 1•20 years ago
|
||
> sDefaultFont = new nsFont(aFont);
> aFont = *sDefaultFont;
I don't see how these are dereferencing errors. Could you elaborate?
nothing makes sure the new doesn't fail. new is an alloc and can fail, presume
we don't throw (because if we throw, the world ends, we try to ask vc6 and gcc
not to throw [we incorrectly encourage vc7 to throw, but that's very much our
fault and a regression]).
| Assignee | ||
Comment 3•20 years ago
|
||
This patch fixes the dereferencing errors, and is a general cleanup of
nsPrintOptionsImpl.*. It does in particular:
* use the new string classes;
* check for pointers/null correctly;
* fix whitespacing and indentation;
* more appropriate code patterns, return from errors immediately;
* use macros for repetitive code;
* null out _retvals;
* ensure that parameter names (at least vaguely) reflect their purpose;
* replaces SetLength(0) with Truncate().
Assignee: printing → baafie
Status: NEW → ASSIGNED
| Assignee | ||
Comment 4•20 years ago
|
||
| Assignee | ||
Comment 5•20 years ago
|
||
Comment on attachment 186174 [details] [diff] [review]
cleanup patch (diff -u)
I did a call for volunteers for reviewing this patch (since printing doesn't
seem covered by any module owners/peers in particular), but there were none.
So, I'm setting asking the same reviewers as I did for the last printing patch.
I Hope that's okay.
Attachment #186174 -
Flags: superreview?(bzbarsky)
Attachment #186174 -
Flags: review?(timeless)
Comment on attachment 186174 [details] [diff] [review]
cleanup patch (diff -u)
i gave feedback to baafie on irc.
Attachment #186174 -
Flags: superreview?(bzbarsky)
Attachment #186174 -
Flags: review?(timeless)
Attachment #186174 -
Flags: review-
Comment 7•20 years ago
|
||
Comment on attachment 186174 [details] [diff] [review]
cleanup patch (diff -u)
+ NS_ERROR("Operator new() returned nsnull; out of memory?");
(maybe timeless already mentioned this, but) you can't use NS_ERROR for OOM.
it's an error you need to handle, you can't assert allocs succeed.
| Assignee | ||
Comment 8•20 years ago
|
||
Summary of timeless' comments:
<timeless> if [you have something in the constructor that] you need to init
something that can fail, it really should be moved to an nsresult Init(){}
method
<timeless> NS_ENSURE_ARG_POINTER(sDefaultFont); ->
NS_ENSURE_STATE(sDefaultFont);
<timeless> NS_ENSURE_ARG_POINTER(ioParamBlock); -> NS_ENSURE_TRUE(.., OOM)
<timeless> [whitespace alignment]
<timeless> + NS_ADDREF(*aPrinterEnumerator =
NS_STATIC_CAST(nsISimpleEnumerator*, printerListEnum));
<timeless> is that cast needed?
<timeless> NS_IMETHODIMP nsPrintOptions::CreatePrintSettings(nsIPrintSettings
**_retval)
<timeless> {
<timeless> + NS_ENSURE_ARG_POINTER(_retval);
<timeless> i think we're not ensuring pointers for outs
<timeless> NS_ENSURE_TRUE -> NS_ENSURE_SUCCESS in some places
<timeless> sprintf(str, "%6.2f", aVal); -> snprintf
All of timeless's comments were addressed; most notably I've added an Init()
method, and made its existence known amongst class factories that inherent the
class, as well as the other consumers.
| Assignee | ||
Updated•20 years ago
|
Attachment #186174 -
Attachment is obsolete: true
Attachment #186364 -
Flags: review?(timeless)
| Assignee | ||
Comment 9•20 years ago
|
||
Attachment #186175 -
Attachment is obsolete: true
| Assignee | ||
Updated•20 years ago
|
Attachment #186364 -
Flags: review?(timeless)
| Assignee | ||
Comment 10•20 years ago
|
||
Let's do it right this time..
Attachment #186364 -
Attachment is obsolete: true
Attachment #186376 -
Flags: review?(timeless)
| Assignee | ||
Comment 11•20 years ago
|
||
Attachment #186365 -
Attachment is obsolete: true
| Assignee | ||
Comment 12•20 years ago
|
||
This patch addresses further comments from timeless, most notably the
following:
* sDefaultFont is no longer declared static, so permanent storage is no longer
required for it. However, the caller of GetDefaultFont() deletes the retrieved
font after using it, without setting the pointer to nsnull. Then, our class
would attempt to delete it a second time upon destruction, which would cause a
crash. The patch therefore includes a small change to
layout/generic/nsSimplePageSequence.cpp, which makes the caller nulls out the
pointer to our default font. Arguably the caller should not be deleting it at
all, but that's a subject for another bug.
* My usage of NS_ENSURE_ARG was replaced by NS_ENSURE_ARG_POINTER, because it
is more appropriate.
* Init() was declared virtual.
* ShowPrintSetupDialog() now has better error checking, an unused nsCOMPtr and
an unneeded assertion were removed.
| Assignee | ||
Updated•20 years ago
|
Attachment #186376 -
Attachment is obsolete: true
Attachment #186425 -
Flags: review?(timeless)
| Assignee | ||
Updated•20 years ago
|
Attachment #186376 -
Flags: review?(timeless)
| Assignee | ||
Comment 13•20 years ago
|
||
Attachment #186377 -
Attachment is obsolete: true
| Assignee | ||
Comment 14•20 years ago
|
||
This patch adds trivial changes such as slightly better error handling and some
more whitespace cleanups.
Attachment #186425 -
Attachment is obsolete: true
Attachment #186866 -
Flags: review?(timeless)
| Assignee | ||
Comment 15•20 years ago
|
||
Attachment #186426 -
Attachment is obsolete: true
| Assignee | ||
Updated•20 years ago
|
Attachment #186425 -
Flags: review?(timeless)
| Reporter | ||
Comment 16•20 years ago
|
||
Comment on attachment 186867 [details] [diff] [review]
cleanup patch, revision 2.1 (diff -w)
>Index: gfx/src/nsPrintOptionsImpl.cpp
>@@ -340,854 +335,931 @@ const char* nsPrintOptions::GetPrefName(
> * This will read in the generic prefs (not specific to a printer)
> * or it will it can read the prefs in using the printer name to qualify
"or it will it can" ?!
>+nsPrintOptions::AvailablePrinters(nsISimpleEnumerator **aPrinterEnumerator)
>+ nsCOMPtr<nsPrinterListEnumerator> printerListEnum =
>+ new nsPrinterListEnumerator();
nsCOMPtr was not designed for non interface creatures, i believe you want
nsRefPtr.
>+nsPrintOptions::WriteInchesFromTwipsPref(const char * aPrefId, nscoord aTwips)
> {
> nsAutoString inchesStr;
> char * str = ToNewCString(inchesStr);
> if (str) {
> mPrefBranch->SetCharPref(aPrefId, str);
doesn't this leak str? :)
>Index: gfx/src/nsPrintOptionsImpl.h
>+class NS_GFX nsPrintOptions : public nsIPrintOptions, public
>+ nsIPrintSettingsService
>+ * method Init
>+ * Initializes member variables. Every consumer that does manual
>+ * addref'ing needs to call this method!
-indicate when and how often-
i think you mean manual creation instead of do_CreateInstance.
>+ * @return nsresult error code
normally we'd list out params as @returns
>+ virtual nsresult Init();
>+ * method WritePrefString
>+ * Writes PRUnichar* to Prefs and deletes the contents of aString
>+ nsresult WritePrefString(const char * aPrefId, const nsAString& aString);
| Assignee | ||
Comment 17•20 years ago
|
||
Address comments.
Attachment #186866 -
Attachment is obsolete: true
Attachment #186913 -
Flags: review?(timeless)
| Assignee | ||
Updated•20 years ago
|
Attachment #186866 -
Flags: review?(timeless)
| Assignee | ||
Comment 18•20 years ago
|
||
Attachment #186867 -
Attachment is obsolete: true
Attachment #186913 -
Flags: superreview?(rbs)
Attachment #186913 -
Flags: review?(timeless)
Attachment #186913 -
Flags: review+
Comment 19•20 years ago
|
||
Comment on attachment 186913 [details] [diff] [review]
cleanup patch, revision 2.2 (diff -u)
I am not interested in super-reviewing this, I don't see much value in such an
invasive cleanup. It messes the bonsai records for little gain.
Attachment #186913 -
Flags: superreview?(rbs)
| Assignee | ||
Comment 20•20 years ago
|
||
Comment on attachment 186913 [details] [diff] [review]
cleanup patch, revision 2.2 (diff -u)
I'll ask bz, in that case.. I <think> he would be willing to do it when he has
time.
Attachment #186913 -
Flags: superreview?(bzbarsky)
Comment 21•20 years ago
|
||
Comment on attachment 186914 [details] [diff] [review]
cleanup patch, revision 2.2 (diff -w)
nsAutoString inchesStr;
inchesStr.AppendFloat(inches);
+ mPrefBranch->SetCharPref(aPrefId, NS_ConvertUTF16toUTF8(inchesStr).get());
OK, why does this use an nsAutoString instead of an nsCAutoString at all?
nsSharedPageData::~nsSharedPageData()
+ mHeadFootFont = nsnull;
why bother? (note that the other Free calls in this function do not set the
pointer to null)
| Assignee | ||
Comment 22•20 years ago
|
||
(In reply to comment #21)
> OK, why does this use an nsAutoString instead of an nsCAutoString at all?
No particular reason. (I'll change it to nsCAutoString)
> nsSharedPageData::~nsSharedPageData()
> + mHeadFootFont = nsnull;
>
> why bother? (note that the other Free calls in this function do not set the
> pointer to null)
See comment #12.
| Assignee | ||
Updated•20 years ago
|
Attachment #186913 -
Flags: superreview?(bzbarsky)
| Assignee | ||
Comment 23•20 years ago
|
||
In this revision, I've addressed biesi's comment about ns[C]AutoString.
In addition, I've removed my change to nsSimplePageSequence.cpp, seeing as
leaving it out doesn't crash my build anymore. The change probably had no
effect anyway, because |delete| is null safe..
At this point I don't understand why the crash was happening in the first
place, but since I can't reproduce it anymore, I'm letting go of this hunk.
Attachment #186914 -
Attachment is obsolete: true
| Assignee | ||
Comment 24•20 years ago
|
||
Attachment #186913 -
Attachment is obsolete: true
Attachment #188243 -
Flags: superreview?(bzbarsky)
Attachment #188243 -
Flags: review-
| Assignee | ||
Updated•20 years ago
|
Attachment #188243 -
Flags: review-
Comment 25•20 years ago
|
||
It'll take me some time to get to this -- I'm still swamped with things that
collected over the last month. You may want to look for someone else to
superreview...
| Assignee | ||
Updated•20 years ago
|
Attachment #188243 -
Flags: superreview?(bzbarsky) → superreview?(dmose)
Comment 26•20 years ago
|
||
Comment on attachment 188243 [details] [diff] [review]
cleanup patch, revision 2.3 (diff -u)
In general it looks good; most of my comments are nit-picking, so addressing
them should be straightforward.
>Index: gfx/idl/nsIPrintOptions.idl
>===================================================================
>RCS file: /cvsroot/mozilla/gfx/idl/nsIPrintOptions.idl,v
>retrieving revision 1.37
>diff -p -8 -u -r1.37 nsIPrintOptions.idl
>--- gfx/idl/nsIPrintOptions.idl 17 Apr 2004 21:52:27 -0000 1.37
>+++ gfx/idl/nsIPrintOptions.idl 4 Jul 2005 12:07:31 -0000
>@@ -87,31 +87,32 @@ interface nsIPrintOptions : nsISupports
>
>- [noscript] void SetFontNamePointSize(in nsNativeStringRef aName, in PRInt32 aPointSize);
>+ [noscript] void SetFontNamePointSize(in AString aName, in PRInt32 aPointSize);
Since the native reference is gone, how about dropping the [noscript]?
>
>-[scriptable, uuid(a6cf9128-15b3-11d2-932e-00805f8add32)]
>+[scriptable, uuid(d9948a4d-f49c-4456-938a-acda2c8d7741)]
>+
I'm confused. Why bump the UUID on the interface after the one that has
actually changed?
>Index: gfx/src/nsPrintOptionsImpl.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/gfx/src/nsPrintOptionsImpl.cpp,v
>retrieving revision 1.73
>diff -p -8 -u -r1.73 nsPrintOptionsImpl.cpp
>--- gfx/src/nsPrintOptionsImpl.cpp 10 Jun 2005 22:18:16 -0000 1.73
>+++ gfx/src/nsPrintOptionsImpl.cpp 4 Jul 2005 12:07:32 -0000
> // Additional Prefs
>-static const char kPrintPaperSize[] = "print_paper_size"; // this has been deprecated
>+// this has been deprecated
>+static const char kPrintPaperSize[] = "print_paper_size";
This makes it look a bit like the comment could apply to everything below it.
Maybe just change the comment to "// deprecated" at the end of the same line?
> nsPrintOptions::~nsPrintOptions()
> {
>- if (sDefaultFont != nsnull) {
>- delete sDefaultFont;
>- sDefaultFont = nsnull;
>+ if (mDefaultFont) {
>+ delete mDefaultFont;
>+ mDefaultFont = nsnull;
> }
> }
What's the point of setting mDefaultFont to nsnull after deleting it? You're
in the destructor, so mDefaultFont is about to go away completely.
>>+NS_IMETHODIMP
> nsPrintOptions::ShowPrintSetupDialog(nsIPrintSettings *aPS)
>+{
>+ NS_ENSURE_ARG_POINTER(aPS);
>+ nsresult rv;
>
>- return rv;
>-
>+ // create a nsISupportsArray of the parameters
>+ // being passed to the window
>+ nsCOMPtr<nsISupportsArray> array;
>+ rv = NS_NewISupportsArray(getter_AddRefs(array));
>+ NS_ENSURE_SUCCESS(rv, rv);
>+
>+ nsCOMPtr<nsISupports> psSupports = do_QueryInterface(aPS);
>+ NS_ASSERTION(psSupports, "PrintSettings must be a supports");
>+
>+ if (psSupports)
>+ array->AppendElement(psSupports);
What's the point of putting this inside an if? There's already an assertion
checking to make sure that you can QI to nsISupports, and if you can't that's a
bug that needs to be fixed, not something that should be checked for at
runtime.
>+
>+ nsCOMPtr<nsIDialogParamBlock> ioParamBlock =
>+ do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &rv);
>+ NS_ENSURE_SUCCESS(rv, rv);
>+
>+ ioParamBlock->SetInt(0, 0);
>+
>+ nsCOMPtr<nsISupports> blkSupps = do_QueryInterface(ioParamBlock);
>+ NS_ASSERTION(blkSupps, "IOBlk must be a supports");
>+ if (blkSupps)
>+ array->AppendElement(blkSupps);
Same question.
>+NS_IMETHODIMP
>+nsPrintOptions::AvailablePrinters(nsISimpleEnumerator **aPrinterEnumerator)
> {
>- NS_ENSURE_ARG_POINTER(aPrinterEnumerator);
>- *aPrinterEnumerator = nsnull;
>+ *aPrinterEnumerator = nsnull;
>
>- nsCOMPtr<nsPrinterListEnumerator> printerListEnum = new nsPrinterListEnumerator();
>- NS_ENSURE_TRUE(printerListEnum.get(), NS_ERROR_OUT_OF_MEMORY);
>+ nsRefPtr<nsPrinterListEnumerator> printerListEnum =
>+ new nsPrinterListEnumerator();
>+ NS_ENSURE_TRUE(printerListEnum, NS_ERROR_OUT_OF_MEMORY);
>
>- nsresult rv = printerListEnum->Init();
>- if (NS_SUCCEEDED(rv)) {
>- *aPrinterEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, printerListEnum);
>- NS_ADDREF(*aPrinterEnumerator);
>- }
>- return rv;
>+ NS_ADDREF(*aPrinterEnumerator = printerListEnum);
>+
>+ nsresult rv = printerListEnum->Init();
>+ if (NS_FAILED(rv))
>+ NS_RELEASE(*aPrinterEnumerator);
>+
>+ return rv;
Instead of calling Init() after the AddRef, call it before. Furthermore, you
can avoid unnecessary pointer dereferences by doing the assignment to the out
param at the very end using the form:
NS_ADDREF(*aPrinterEnumerator = printerListEnum.get())
>
>-NS_IMETHODIMP nsPrintOptions::DisplayJobProperties( const PRUnichar *aPrinter, nsIPrintSettings* aPrintSettings, PRBool *aDisplayed)
>+NS_IMETHODIMP
>+nsPrintOptions::DisplayJobProperties(const PRUnichar *aPrinter,
>+ nsIPrintSettings* aPrintSettings,
>+ PRBool *aDisplayed)
> {
>- NS_ENSURE_ARG(aPrinter);
>- *aDisplayed = PR_FALSE;
>+ NS_ENSURE_ARG_POINTER(aPrinter);
>+ *aDisplayed = PR_FALSE;
>+
>+ nsresult rv;
>+ nsCOMPtr<nsIPrinterEnumerator> propDlg;
>
>- nsresult rv;
>- nsCOMPtr<nsIPrinterEnumerator> propDlg;
>+ propDlg = do_CreateInstance(kCPrinterEnumerator, &rv);
>+ NS_ENSURE_SUCCESS(rv, rv);
>
>- propDlg = do_CreateInstance(kCPrinterEnumerator, &rv);
>- if (NS_FAILED(rv))
>- return rv;
>+ NS_ENSURE_ARG_POINTER(aPrintSettings);
>+ rv = propDlg->DisplayPropertiesDlg((PRUnichar*)aPrinter, aPrintSettings);
Prefer C++ style casts to C-style casts, since they express intent more
precisely and thus allow the compiler to catch more bugs at build time. In
this case, NS_CONST_CAST is what you want.
>-/* [noscript] voidPtr GetNativeData (in short aDataType); */
> NS_IMETHODIMP nsPrintOptions::GetNativeData(PRInt16 aDataType, void * *_retval)
> {
>- NS_ENSURE_ARG_POINTER(_retval);
> *_retval = nsnull;
>-
> return NS_ERROR_NOT_IMPLEMENTED;
> }
Might as well get rid of the |*retval = nsnull| line here; you're already
returning an error, so you don't need to guarantee that *retval is set to
anything in particular.
> nsresult nsPrintOptions::_CreatePrintSettings(nsIPrintSettings **_retval)
> {
> nsresult rv = NS_OK;
>+ *_retval = nsnull;
The above line shouldn't be necessary; see previous comment. There seem to be
more instances of this pattern throughout the patch. None should be necessary
and just waste cycles.
>- nsPrintSettings * printSettings = new nsPrintSettings(); // does not initially ref count
>+ // does not initially ref count
>+ nsPrintSettings * printSettings = new nsPrintSettings();
> NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY);
>
> NS_ADDREF(*_retval = printSettings); // ref count
>- InitPrintSettingsFromPrefs(*_retval, PR_FALSE, nsIPrintSettings::kInitSaveAll); // ignore return value
>+ InitPrintSettingsFromPrefs(*_retval, PR_FALSE,
>+ nsIPrintSettings::kInitSaveAll);
>+ // ignore return value
A good way to indicate that a return value is intentionally ignore is simply to
cast the call itself to void.
> return rv;
> }
>
>-/* nsIPrintSettings CreatePrintSettings (); */
> NS_IMETHODIMP nsPrintOptions::CreatePrintSettings(nsIPrintSettings **_retval)
> {
>+ *_retval = nsnull;
> return _CreatePrintSettings(_retval);
> }
What's the point of having this split into two functions? Why not just move
all the code in _CreatePrintSettings here?
>+nsresult
>+nsPrintOptions::ReadPrefString(const char * aPrefId, nsAString& aString)
> {
> NS_ENSURE_STATE(mPrefBranch);
>+ NS_ENSURE_ARG_POINTER(aPrefId);
>+
> char * str = nsnull;
> nsresult rv = mPrefBranch->GetCharPref(aPrefId, &str);
>- if (NS_SUCCEEDED(rv) && str) {
>- CopyUTF8toUTF16(str, aString);
>- nsMemory::Free(str);
>+ if (NS_SUCCEEDED(rv)) {
>+ // By encapsulating str, we save copying and freeing it
>+ aString = nsDependentString((NS_ConvertUTF8toUTF16(str)));
> }
> return rv;
> }
The above code will leak, because str itself is never freed. Since
NS_ConvertUTF8toUTF16 is itself implicitly copying the string into a stack
variable, there's no real savings there either. Additionally, this code is
attempting to return a string dependant on a stack variable which is about to
go out of scope. Either this is going to force a second copy, or else you'll
have a bug; I'm not sure which. I'd vote with leaving this function that way
it was before.
>+void
>+nsPrintOptions::WriteInchesFromTwipsPref(const char * aPrefId, nscoord aTwips)
> {
>- if (!mPrefBranch) {
>+ if (!mPrefBranch)
> return;
>- }
Why get rid of the braces here? It's an invitation to a future error if
someone
decides to add some other piece of code to the else clause but forgets to add
them back.
Attachment #188243 -
Flags: superreview?(dmose) → superreview-
Comment 27•20 years ago
|
||
>+ aString = nsDependentString((NS_ConvertUTF8toUTF16(str)));
yeah, that should absolutely stay with CopyUTF8toUTF16. I'm surprised that you
can construct an nsDependentString like that...
maybe that function should also use nsXPIDLCString.
| Assignee | ||
Comment 28•20 years ago
|
||
This patch addresses dmose's comments.
Attachment #188243 -
Attachment is obsolete: true
Attachment #189056 -
Flags: superreview?(dmose)
| Assignee | ||
Updated•20 years ago
|
Attachment #189056 -
Flags: superreview?(dmose)
| Assignee | ||
Comment 29•20 years ago
|
||
The right patch this time.
Attachment #189056 -
Attachment is obsolete: true
| Assignee | ||
Comment 30•20 years ago
|
||
Attachment #188241 -
Attachment is obsolete: true
| Assignee | ||
Updated•20 years ago
|
Attachment #189059 -
Flags: superreview?(dmose)
| Assignee | ||
Comment 31•20 years ago
|
||
timeless mentioned that when removing [noscript], I should switch from
InitialCaps to interCaps.
Attachment #189059 -
Attachment is obsolete: true
Attachment #189307 -
Flags: superreview?(dmose)
| Assignee | ||
Updated•20 years ago
|
Attachment #189059 -
Flags: superreview?(dmose)
| Assignee | ||
Comment 32•20 years ago
|
||
Attachment #189060 -
Attachment is obsolete: true
Comment 33•20 years ago
|
||
Comment on attachment 189307 [details] [diff] [review]
cleanup patch, revision 2.5.1 (diff -u)
sr=dmose
Attachment #189307 -
Flags: superreview?(dmose) → superreview+
| Assignee | ||
Updated•20 years ago
|
Attachment #189307 -
Flags: approval1.8b4?
Updated•20 years ago
|
Attachment #189307 -
Flags: approval1.8b4? → approval1.8b4+
| Assignee | ||
Comment 34•20 years ago
|
||
Checked in by timeless (2005-07-19 14:55). Thanks guys!
Status: ASSIGNED → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
Comment 35•20 years ago
|
||
This caused a bunch of issues on Mac; see bug 306370.
Updated•14 years ago
|
Crash Signature: [@ nsPrintOptions::_CreatePrintSettings]
You need to log in
before you can comment on or make changes to this bug.
Description
•