UNINITIALIZED READs related to NtGdi syscalls found on Chromium #502

Open
derekbruening opened this Issue Nov 28, 2014 · 15 comments

Comments

Projects
None yet
1 participant
Contributor

derekbruening commented Nov 28, 2014

From bruen...@google.com on July 20, 2011 16:54:38

split from issue #501 :

Also seen on Chromium w/o symbols, looks related:

Error #1: UNINITIALIZED READ: reading 0x003cbe58-0x003cbe5c 4 byte(s) within 0x003cbe58-0x003cbe5c
@0:01:26.148 in thread 2840
system call NtGdiEnumFonts

0x759ec264 <GDI32.dll+0x1c264> GDI32.dll!CreateICW
0x759ec3d9 <GDI32.dll+0x1c3d9> GDI32.dll!EnumFontFamiliesExW
0x726eea4e <RICHED20.dll+0xea4e> RICHED20.dll!CreateTextServices
0x726edc98 <RICHED20.dll+0xdc98> RICHED20.dll!IID_ITextServices
0x726ed54a <RICHED20.dll+0xd54a> RICHED20.dll!IID_IRichEditOleCallback
0x726ee895 <RICHED20.dll+0xe895> RICHED20.dll!CreateTextServices
0x726ee871 <RICHED20.dll+0xe871> RICHED20.dll!CreateTextServices
0x726e220c <RICHED20.dll+0x220c> RICHED20.dll!?
0x75e96238 <USER32.dll+0x16238> USER32.dll!gapfnScSendMessage
0x75e968ea <USER32.dll+0x168ea> USER32.dll!gapfnScSendMessage
0x75ea0ab0 <USER32.dll+0x20ab0> USER32.dll!FillRect
0x75ea0ad6 <USER32.dll+0x20ad6> USER32.dll!CallWindowProcW
0x5d221b87 <chrome.dll+0x1b91b87> chrome.dll!ATL::CWindowImplBaseTWTL::CRichEditCtrlTATL::CWindow,ATL::CWinTraits<1342177664,0 >::DefWindowPro
c:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\atlwin.h:3030
0x5d223778 <chrome.dll+0x1b93778> chrome.dll!ATL::CWindowImplBaseTWTL::CRichEditCtrlTATL::CWindow,ATL::CWinTraits<1342177664,0 >::WindowProc
c:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\atlwin.h:3089
0x75e96238 <USER32.dll+0x16238> USER32.dll!gapfnScSendMessage
0x75e968ea <USER32.dll+0x168ea> USER32.dll!gapfnScSendMessage
0x75e9cd1a <USER32.dll+0x1cd1a> USER32.dll!GetWindow
0x75e9cd81 <USER32.dll+0x1cd81> USER32.dll!SendMessageW
0x5d21af26 <chrome.dll+0x1b8af26> chrome.dll!ATL::CWindow::SetFont
c:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\atlwin.h:864

Original issue: http://code.google.com/p/drmemory/issues/detail?id=502

Contributor

derekbruening commented Nov 28, 2014

From bruen...@google.com on July 20, 2011 13:55:27

what test suite is this on?

Owner: timurrrr@google.com

Contributor

derekbruening commented Nov 28, 2014

From timurrrr@google.com on July 21, 2011 02:53:25

I've seen this on reliability_tests which basically runs full Chromium on different URLs.
I'll try to reduce

Contributor

derekbruening commented Nov 28, 2014

From timurrrr@google.com on July 25, 2011 06:27:51

One more:
UNINITIALIZED READ: reading 0x0028cae4-0x0028cae8 4 byte(s) within 0x0028cae4-0x0028cae8

1 <sys.call> NtGdiIntersectClipRect

2 SystemParametersInfoW USER32.dll+0x21155

3 DrawTextExW USER32.dll+0x213d6

4 DrawTextW USER32.dll+0x2232e

5 `anonymous namespace'::DoDrawText ui\gfx\canvas_skia_win.cc:47

6 gfx::CanvasSkia::SizeStringInt ui\gfx\canvas_skia_win.cc:320

7 gfx::CanvasSkia::DrawFadeTruncatingString ui\gfx\canvas_skia_win.cc:477

Summary: UNINITIALIZED READs related to NtGdi syscalls found on Chromium

Contributor

derekbruening commented Nov 28, 2014

From bruen...@google.com on July 25, 2011 10:29:47

suspicious: NtGdiIntersectClipRect doesn't have optional parameters
TOFILE: which param is that, can't tell from stack address

Contributor

derekbruening commented Nov 28, 2014

From zhao...@google.com on August 28, 2012 13:56:16

See similar error report:
Dr.M Error #1: UNINITIALIZED READ: reading 0x0018f20c-0x0018f210 4 byte(s) within 0x0018f20c-0x0018f210
Dr.M # 0 system call NtGdiEnumFonts parameter #6
Dr.M # 1 GDI32.dll!bEnumFonts
Dr.M # 2 GDI32.dll!EnumFontsInternalW
Dr.M # 3 GDI32.dll!EnumFontsInternalA
Dr.M # 4 GDI32.dll!EnumFontFamiliesExA

This one looks like a false positive:

GDI32!EnumFontsInternalW:
7587c3e2 8bff mov edi,edi
7587c3e4 55 push ebp
7587c3e5 8bec mov ebp,esp
7587c3e7 83ec0c sub esp,0xc
7587c3ea 53 push ebx
7587c3eb 6a00 push 0x0
7587c3ed 33db xor ebx,ebx
7587c3ef 6a00 push 0x0
7587c3f1 43 inc ebx
7587c3f2 e8e0ffffff call GDI32!GetAppCompatFlags (7587c3d7)
7587c3f7 6a00 push 0x0
7587c3f9 8d4dfc lea ecx,[ebp-0x4]
7587c3fc 51 push ecx

ecx is pointing to the memory allocated by "7587c3e7 83ec0c: sub esp,0xc", which is not initialized.
It is partially initialized

7587c3fd 50 push eax
7587c3fe ff751c push dword ptr [ebp+0x1c]
7587c401 8945f8 mov [ebp-0x8],eax

then calls to GDI32!bEnumFonts
7587c404 ff7510 push dword ptr [ebp+0x10]
7587c407 ff750c push dword ptr [ebp+0xc]
7587c40a ff7508 push dword ptr [ebp+0x8]
7587c40d e8cd000000 call GDI32!bEnumFonts (7587c4df)
7587c401 8945f8 mov [ebp-0x8],eax

GDI32!bEnumFonts calls to the system call without filling that either:

GDI32!bEnumFonts:
7587c4df 8bff mov edi,edi
7587c4e1 55 push ebp
7587c4e2 8bec mov ebp,esp
7587c4e4 837d0c00 cmp dword ptr [ebp+0xc],0x0
7587c4e8 0f84cae0ffff je GDI32!bEnumFonts+0x22 (7587a5b8)
... // no other ebp update
GDI32!bEnumFonts+0x24:
7587c503 ff7520 push dword ptr [ebp+0x20]
7587c506 ff751c push dword ptr [ebp+0x1c] // The pointer
7587c509 ff7510 push dword ptr [ebp+0x10]
7587c50c ff750c push dword ptr [ebp+0xc]
7587c50f 50 push eax
7587c510 ff7518 push dword ptr [ebp+0x18]
7587c513 ff7514 push dword ptr [ebp+0x14]
7587c516 ff7508 push dword ptr [ebp+0x8]
7587c519 e809000000 call GDI32!NtGdiEnumFonts (7587c527)
7587c51e 5d pop ebp
7587c51f c21c00 ret 0x1c

So the pointer is actually partially initialized.

from syscall_wingdi.c
{0,"NtGdiEnumFonts", OK, 32, {{4,-3,R|SYSARG_SIZE_IN_ELEMENTS,sizeof(wchar_t)}, {6,sizeof(ULONG),R|W,}, {7,-6,WI,}, }},

Contributor

derekbruening commented Nov 28, 2014

From zhao...@google.com on August 28, 2012 14:02:58

It seems param #6 should be W only for this case.

Contributor

derekbruening commented Nov 28, 2014

From zhao...@google.com on August 28, 2012 14:05:40

before and after the system call, the value changed:
pre-syscall
0018f20c 0018f234
0018f210 0018f240
0018f214 7588259c GDI32!EnumFontsInternalA+0x68

post-syscall
0018f20c 00047044
0018f210 0018f240
0018f214 7588259c GDI32!EnumFontsInternalA+0x68

Contributor

derekbruening commented Nov 28, 2014

From bruen...@google.com on August 28, 2012 14:16:49

the header has it as R|W:

__inout ULONG *pulCount,
__out_bcount_opt(*pulCount) void * pvUserModeBuffer

what do you mean, "the pointer is partially initialized": can you point out where it's partially set? at a glance I only see whole-word operations in the disasm.

Owner: zhao...@google.com

Contributor

derekbruening commented Nov 28, 2014

From zhao...@google.com on August 28, 2012 14:22:32

7587c401 8945f8 mov [ebp-0x8],eax
I thought it was a pointer pointing to some buffer, so said it is partially initialized.

Contributor

derekbruening commented Nov 28, 2014

From bruen...@google.com on August 28, 2012 14:26:48

I thought it was a pointer pointing to some buffer, so said it is partially initialized.

as you yourself showed in the table entry you pasted, it's a pointer to ULONG. I'm asking where that ULONG is partially initialized.

Contributor

derekbruening commented Nov 28, 2014

From zhao...@google.com on August 28, 2012 14:29:45

At beginning, I thought it was a pointer pointing to some data structure (not ULONG) starting at [ebp - 0x4], and later there is an update on [ebp - 0x8], so I said it is partially set.

If it is ULONG, then it is not partially set.

Contributor

derekbruening commented Nov 28, 2014

From zhao...@google.com on August 28, 2012 14:33:07

pre-syscall
0:000> dds 0x18f1b8
0018f1b8 7587c51e GDI32!bEnumFonts+0x3f
0018f1bc d90117ea
0018f1c0 00000003
0018f1c4 00000000
0018f1c8 00000000
0018f1cc 00000000
0018f1d0 00000001
0018f1d4 0018f20c
0018f1d8 00000000
0018f1dc 0018f210
0018f1e0 7587c412 GDI32!EnumFontsInternalW+0x30
0018f1e4 d90117ea
0018f1e8 00000000
0018f1ec 00000001
0018f1f0 00000003
0018f1f4 00000000
0018f1f8 0018f20c
0018f1fc 00000000
0018f200 00000000
0018f204 0018f230
0018f208 00000000
0018f20c 0018f234
0018f210 0018f240
0018f214 7588259c GDI32!EnumFontsInternalA+0x68

post-syscall

0018f1b8 7587c51e GDI32!bEnumFonts+0x3f
0018f1bc d90117ea
0018f1c0 00000003
0018f1c4 00000000
0018f1c8 00000000
0018f1cc 00000000
0018f1d0 00000001
0018f1d4 0018f20c
0018f1d8 00000000
0018f1dc 0018f210
0018f1e0 7587c412 GDI32!EnumFontsInternalW+0x30
0018f1e4 d90117ea
0018f1e8 00000000
0018f1ec 00000001
0018f1f0 00000003
0018f1f4 00000000
0018f1f8 0018f20c
0018f1fc 00000000
0018f200 00000000
0018f204 0018f230
0018f208 00000000
0018f20c 00047044
0018f210 0018f240
0018f214 7588259c GDI32!EnumFontsInternalA+0x68

Contributor

derekbruening commented Nov 28, 2014

From bruen...@google.com on August 28, 2012 14:56:21

so the pvUserModeBuffer is NULL. perhaps when NULL is passed, the count is just OUT and the kernel indicates the size so the app can call again. did the syscall fail w/ one of the codes listed for SYSINFO_RET_SMALL_WRITE_LAST?

Contributor

derekbruening commented Nov 28, 2014

From bruen...@google.com on August 28, 2012 15:00:08

ok it returns bool instead of a status. and the buffer is listed as optional. so perhaps when it's NULL it still writes the size needed.

Contributor

derekbruening commented Nov 28, 2014

From zhao...@google.com on August 28, 2012 15:04:46

Does it means the param#6'sR is conditional, i.e. depends on if the pvUserModeBuffer is NULL

derekbruening removed the Type-Bug label Apr 2, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment