JDK-4225868 : Plug-In 1.2.1 L can crash browser on Windows '98
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.2.0,1.2.1,1.2.2
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_98,windows_nt
  • CPU: x86
  • Submitted: 1999-04-01
  • Updated: 1999-04-29
  • Resolved: 1999-04-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.2.2 1.2.2Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Description
Using the keyboard shortcuts to bring up a dialog in the SwingSet applet causes the browser to crash under Windows '98.

To reproduce:
(Windows '98, IE or Netscape)
Install Plug-In from the jdk1.2.1 'L' build
Go to the BrowserSuite test page:
	http://javaweb/~nancys/BrowserSuiteJ/Suite/QLhtml/1/index.html
and select the SwingSetApplet link
After the SwingSet applet loads, hit Alt+D to bring up the Dialogs menu, then USING THE KEYBOARD select the Component Dialog menu item and hit return.
This should cause the browser to crash. If it doesn't try it a couple more times.

Here is the trace from the crash generated by Windows '98:

NETSCAPE caused a stack fault in module AWT.DLL at 015f:50320bf7.
Registers:
EAX=000042d4 CS=015f EIP=50320bf7 EFLGS=00010206
EBX=04c72434 SS=0167 ESP=042944b4 EBP=0429b7c0
ECX=042914bc DS=0167 ESI=00e14c70 FS=4887
EDX=81b80000 ES=0167 EDI=78001539 GS=0000
Bytes at CS:EIP:
85 01 3d 00 10 00 00 73 ec 2b c8 8b c4 85 01 8b 
Stack dump:
04cacc98 5027a095 6176614a 294d5428 756c5020 6e692d67 6556203a 6f697372 2e31206e 2e312e32 550a0d6c 676e6973 45524a20 72657620 6e6f6973 322e3120 

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: generic FIXED IN: 1.2.2 INTEGRATED IN: 1.2.2 VERIFIED IN: 1.2.2
14-06-2004

SUGGESTED FIX ------- awt_Window.cpp ------- *** /tmp/dXuayje Mon Apr 26 20:20:47 1999 --- awt_Window.cpp Mon Apr 26 19:56:36 1999 *************** *** 191,204 **** */ RECT outside; RECT inside; ::GetWindowRect(GetHWnd(), &outside); - ::GetClientRect(GetHWnd(), &inside); /* Update our inset member */ if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) { ::MapWindowPoints(GetHWnd(), 0, (LPPOINT)&inside, 2); m_insets.top = inside.top - outside.top; ! m_insets.bottom = outside.bottom - inside.bottom; m_insets.left = inside.left - outside.left; m_insets.right = outside.right - inside.right; } else { --- 191,219 ---- */ RECT outside; RECT inside; + int extraBottomInsets = 0; + ::GetWindowRect(GetHWnd(), &outside); + jobject target = GetTarget(env); + jstring warningString = + (jstring)(env)->GetObjectField(target, AwtWindow::warningStringID); + if (warningString != NULL) { + ::CopyRect(&inside, &outside); + DefWindowProc(WM_NCCALCSIZE, FALSE, (LPARAM)&inside); + extraBottomInsets = ::GetSystemMetrics(SM_CYCAPTION) + + ((GetStyle() & WS_THICKFRAME) ? 2 : -2); + } else { + ::GetClientRect(GetHWnd(), &inside); + } + env->DeleteLocalRef(target); + env->DeleteLocalRef(warningString); + /* Update our inset member */ if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) { ::MapWindowPoints(GetHWnd(), 0, (LPPOINT)&inside, 2); m_insets.top = inside.top - outside.top; ! m_insets.bottom = outside.bottom - inside.bottom + extraBottomInsets; m_insets.left = inside.left - outside.left; m_insets.right = outside.right - inside.right; } else { *************** *** 234,239 **** --- 249,255 ---- m_insets.top += ::GetSystemMetrics(SM_CYMENU); } } + m_insets.bottom += extraBottomInsets; env->DeleteLocalRef(target); } *************** *** 533,540 **** } else { m_warningRect.top += 2; } - lpncsp->rgrc[0].bottom = m_warningRect.top; /* Convert to window-relative coordinates. */ ::OffsetRect(&m_warningRect, -r.left, -r.top); --- 549,559 ---- } else { m_warningRect.top += 2; } + lpncsp->rgrc[0].bottom = (m_warningRect.top >= lpncsp->rgrc[0].top) + ? m_warningRect.top + : lpncsp->rgrc[0].top; + /* Convert to window-relative coordinates. */ ::OffsetRect(&m_warningRect, -r.left, -r.top);
11-06-2004

EVALUATION According to the bug report, the crash is in AWT.DLL. thomas.ball@Eng 1999-04-01 Using the attached Dr. Watson and map files, I reconstructed the following stack trace: unknown (KERNEL32.DLL, .text+0xeeb5) unknown (015f:ffecbad7, probably garbage) _Java_sun_awt_windows_WTextAreaPeer_insertText (AWT_G.DLL, .text+0xab3e4) _sysInvokeNative (JVM_G.DLL, .text+0x74fde) _invokeJNINativeMethod (JVM_G.DLL, .text+0xd7e6) _ExecuteJava_C (JVM_G.DLL, .text+0x2c0d5) _do_execute_java_method_vararg (JVM_G.DLL, .text+0x1e0d8) _execute_java_dynamic_method (JVM_G.DLL, .text+0x1d8ab) _exceptionDescribe (JVM_G.DLL, .text+10c19) _AddToLoadedClasses (JVM_G.DLL, .text+36338) _JNI_GetCreatedJavaVMs@12 (JVM_G.DLL, .text+3e436) ?ExceptionDescribe@JNIEnv_@@QAEXXZ (AWT_G.DLL, .text+0x7f2e3) ?SendEvent@AwtObject@@QAEXPAV_jobject@@@Z (AWT_G.DLL, .text+0xa2099) ?SendFocusEvent@AwtComponent@@QAEXJH@Z (AWT_G.DLL, .text+0x7a5ed) ?WmKillFocus@AwtComponent@@UAE?AW4MsgRouting@@PAX@Z (AWT_G.DLL, .text+0x763d1) ?WindowProc@AwtComponent@@UAEJIIJ@Z (AWT_G.DLL, .text+0x75788) ?WndProc@AwtComponent@@SGJPAXIIJ@Z (AWT_G.DLL, .text+0x7471d) unknown (KERNEL32.DLL, _FREQASM+0x263b) unknown (KERNEL32.DLL, .text+0x1b2e7) In this stack, the user has generated a WM_KILLFOCUS message by bringing up a new dialog. We construct a java.awt.event.FocusEvent in response to this and try to post it to the event queue. WComponentPeer.postEvent(AWTEvent) fails with some exception. We detect the exception and try to describe it. The VM dumps the stack trace to the Plug-in Java Console window. While attempting to insert text in the Console window, we segfault. david.mendenhall@eng 1999-04-11 I suspect that we are trying to alloca too much space and in the process corrupting the stack (hence the bogus address at the top). The Win95 (but not the WinNT) implementation of replaceText makes two calls to alloca via the W2A preprocessor macros. We've been burned by this before; we should remove ALL calls to alloca from the AWT source once and for all. david.mendenhall@eng 1999-04-11 I removed all calls to alloca. The crash is now less frequent, but still happens. One time, the console window displayed "java.lang.ClassCastException" and then scrolled up for about 3 seconds before crashing. david.mendenhall@eng 1999-04-14 I have finally determined the root cause of the plug-in crash we've been investigating for several weeks now. First of all, it's important to note that this crash isn't a race condition. At the time the buggy code executes, the AWT is single-threaded (only the Toolkit thread is running and all other threads are blocked waiting). In AwtWindow::WmNcCalcSize, we calculate the size of a Window's client area by taking the default values Windows supplies for us, and adjusting those values for the size of the warning string, if there is one. We set the bottom of the client area to the top of the warning string, where the top of the warning string is defined as the bottom of the warning string minus (essentially) a constant. This calculation is correct in the general case, but is invalid when the size of the Window is small. In that case, we end up placing the bottom of the rectangle above the top. The invalid bottom value is passed back to the Windows USER DLL, where it can then cause memory corruption on Windows 98. Unfortunately, since all Windows begin with zero height and zero width, this invalid calculation is performed on creation of any Window. The fix is simple: ------- awt_Window.cpp ------- 536c536,538 < lpncsp->rgrc[0].bottom = m_warningRect.top; --- > lpncsp->rgrc[0].bottom = (m_warningRect.top >= lpncsp->rgrc[0].top) > ? m_warningRect.top > : lpncsp->rgrc[0].top; The next question is why did the fix I found last week work at all. It appears that the reshape and initialization routine for Windows and Frames generates fewer calls to WmNcCalcSize than the routine for Dialogs. The additional calls are all generated before the Dialog is made resizable, and thus when its insets are smaller than a resizable Dialog's. The smaller insets probably cross the boundrary of the edge condition inside Windows, triggering the corruption. Altering the Dialog initialization routine prevented these additional calls to WmNcCalcSize. However, I supsect that last week's fix would not have prevented crashes for non-resizable Dialogs. Changing the Dialog code is still good engineering. It makes the code more efficient, and makes it consistent with the Window and Frame code. We should putback the change to the Dialog code at some point, but only the change to awt_Window.cpp is absolutely required for now. david.mendenhall@eng 1999-04-25 Robi pointed out that we rely on the bogus return rectangle from WmNcCalcSize in order to compute the correct insets for the Window. Thus, making the rectangle valid broke the insets calculation. This regression was observable in /java/jdk/ws/awt/dpm/cricket/test/java/awt/Frame/WarningSizeTest. To correct the problem, I decoupled UpdateInsets from GetClientRect when the Window has a warning string. Instead, I call DefWindowProc for WM_NCCALCSIZE and then adjust the resulting client rectangle just like WmNcCalcSize does. I have verified on 98 and NT that the inset values with the new build are equivalent to those of 1.2fcs. Incidentally, I think the reason we were seeing Dialog packing problems in SwingSet when the warning string was active, is that we return immediately from WmNcCalcSize if fCalcValidRects is FALSE. As far as I can tell, this is wrong. A FALSE value for fCalcValidRects merely indicates the type of lParam is an LPRECT instead of an LPNCCALCSIZE_PARAMS. The rectangle should still be filled in with a valid client rectangle. david.mendenhall@eng 1999-04-26
26-04-1999