Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False pos: 80 byte leak from plfCreateLOCALFONT on Win7 #733

Open
derekbruening opened this issue Nov 28, 2014 · 4 comments
Open

False pos: 80 byte leak from plfCreateLOCALFONT on Win7 #733

derekbruening opened this issue Nov 28, 2014 · 4 comments

Comments

@derekbruening
Copy link
Contributor

From rnk@google.com on January 04, 2012 16:35:58

I only seem to get this error report on my workstation. It started happening a few weeks before the holidays, and since then I've been unable to run the drmemory suite and have been relying on the bots to run the full suite.

Here is the leak:

Dr.M Error #1: POSSIBLE LEAK 80 direct bytes 0x00fc34b0-0x00fc3500 + 0 indirect bytes
Dr.M # 0 GDI32.dll!plfCreateLOCALFONT
Dr.M # 1 GDI32.dll!CreateFontIndirectExW
Dr.M # 2 GDI32.dll!CreateFontIndirectW
Dr.M # 3 UxTheme.dll!CInternalNonclientMetrics::Acquire
Dr.M # 4 UxTheme.dll!NcGetNonclientMetrics
Dr.M # 5 UxTheme.dll!AcquireNcThemeMetrics
Dr.M # 6 UxTheme.dll!OnHooksEnabled
Dr.M # 7 USER32.dll!InitUserApiHook
Dr.M # 8 USER32.dll!__ClientLoadLibrary
Dr.M # 9 ntdll.dll!KiUserCallbackDispatcher
Dr.M #10 sophos_detoured.dll!Detoured +0x38 (0x6fa09579 <sophos_detoured.dll+0x9579>)
Dr.M #11 sophos_detoured.dll!spmaa_finalise2 +0x1ca6 (0x6fa19267 <sophos_detoured.dll+0x19267>)

I ran with a higher verbosity to see who points to it:

defined range 0x01200000-0x01381000
(0x0120b830 points to mid-chunk 0x02a70d00 in 0x02a70a20-0x02a71220)
(0x0120b980 points to mid-chunk 0x02a70b60 in 0x02a70a20-0x02a71220)
(0x01215838 points to mid-chunk 0x00fc34f8 in 0x00fc34b0-0x00fc3500) *** our chunk
(0x01215a00 points to mid-chunk 0x00fc34f0 in 0x00fc34b0-0x00fc3500) *** our chunk
...
defined range 0x76be0000-0x76be1000
(0x76be0030 points to mid-chunk 0x00fc34e8 in 0x00fc34b0-0x00fc3500) *** our chunk
is_vtable 0x00fc34e0: 2, 3

The chunk itself:

defined range 0x00fc34b0-0x00fc3500
(0x00fc34b8 points to start of its own chunk 0x00fc34b0-0x00fc3500)
(0x00fc34c0 points to middle 0x00fc34b8 of its own chunk 0x00fc34b0-0x00fc3500)
(0x00fc34c8 points to middle 0x00fc34c0 of its own chunk 0x00fc34b0-0x00fc3500)
(0x00fc34d0 points to middle 0x00fc34c8 of its own chunk 0x00fc34b0-0x00fc3500)
(0x00fc34d8 points to middle 0x00fc34d0 of its own chunk 0x00fc34b0-0x00fc3500)
(0x00fc34e0 points to middle 0x00fc34d8 of its own chunk 0x00fc34b0-0x00fc3500)
(0x00fc34e8 points to middle 0x00fc34e0 of its own chunk 0x00fc34b0-0x00fc3500)

So, it looks like there is a global that points to the last element of this array, and the array itself is basically a linked list, where each node is 8 bytes and points to a node 8 bytes prior.

This seems to be exactly what GDI32.dll!plfCreateLOCALFONT does. Here are the basic blocks:

in event_basic_block(tag=0x76b95b4d)
new basic block @0x76b95b4d == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95b4d
+0 L3 8b ff mov %edi -> %edi
+2 L3 55 push %ebp %esp -> %esp 0xfffffffc(%esp)
+3 L3 8b ec mov %esp -> %ebp
+5 L3 56 push %esi %esp -> %esp 0xfffffffc(%esp)
+6 L3 8b 35 30 00 be 76 mov 0x76be0030 -> %esi
+12 L3 85 f6 test %esi %esi
+14 L3 0f 84 b2 02 00 00 jz $0x76b95e13
END 0x76b95b4d

in event_basic_block(tag=0x76b95e13)
new basic block @0x76b95e13 == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95e13
+0 L3 64 a1 18 00 00 00 mov %fs:0x18 -> %eax
+6 L3 8b 40 30 mov 0x30(%eax) -> %eax
+9 L3 6a 50 push $0x00000050 %esp -> %esp 0xfffffffc(%esp) # 80 bytes
+11 L3 6a 00 push $0x00000000 %esp -> %esp 0xfffffffc(%esp)
+13 L3 ff 70 18 push 0x18(%eax) %esp -> %esp 0xfffffffc(%esp)
+16 L3 ff 15 a8 01 b9 76 call 0x76b901a8 %esp -> %esp 0xfffffffc(%esp)
END 0x76b95e13

**** Malloc of 0x00fc34b0 happens here

alloc_hook retaddr=0x76b95e29
found new retaddr: call to RtlAllocateHeap from 0x76b95e29 non-instru
entering alloc routine 0x7765e026 RtlAllocateHeap indirect rec=0 adj=0 post-retaddr
alloc type: 4
malloc-pre heap=0x00f60000 size=0x50 flags=0x0
in event_basic_block(tag=0x76b95e29)
new basic block @0x76b95e29 == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95e29
+0 L3 8b f0 mov %eax -> %esi
+2 L3 6a 08 push $0x00000008 %esp -> %esp 0xfffffffc(%esp)
+4 L3 85 f6 test %esi %esi
+6 L3 74 09 jz $0x76b95e3a # Check for null pointer
END 0x76b95e29

in event_basic_block(tag=0x76b95e31)
new basic block @0x76b95e31 == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95e31
+0 L3 83 26 00 and $0x00000000 (%esi) -> (%esi)
+3 L3 83 c6 08 add $0x00000008 %esi -> %esi
+6 L3 58 pop %esp (%esp) -> %eax %esp # eax is 0x08 from earlier push
+7 L3 eb 0a jmp $0x76b95e44
END 0x76b95e31

in event_basic_block(tag=0x76b95e44)
new basic block @0x76b95e44 == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95e44
+0 L3 8d 4e f8 lea 0xfffffff8(%esi) -> %ecx # Gets addr of prev node
+3 L3 89 0e mov %ecx -> (%esi) # Stores to probable "next" field
+5 L3 83 c6 08 add $0x00000008 %esi -> %esi
+8 L3 48 dec %eax -> %eax
+9 L3 75 f5 jnz $0x76b95e44
END 0x76b95e44

in event_basic_block(tag=0x76b95e4f)
new basic block @0x76b95e4f == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95e4f
+0 L3 8d 46 f8 lea 0xfffffff8(%esi) -> %eax
+3 L3 e9 0c fd ff ff jmp $0x76b95b63
END 0x76b95e4f

in event_basic_block(tag=0x76b95b63)
new basic block @0x76b95b63 == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95b63
+0 L3 a3 30 00 be 76 mov %eax -> 0x76be0030 # Store final element to global
+5 L3 85 f6 test %esi %esi
+7 L3 74 09 jz $0x76b95b75
END 0x76b95b63

in event_basic_block(tag=0x76b95b6c)
new basic block @0x76b95b6c == GDI32.dll!plfCreateLOCALFONT
TAG 0x76b95b6c
+0 L3 8b 45 08 mov 0x08(%ebp) -> %eax
+3 L3 83 66 04 00 and $0x00000000 0x04(%esi) -> 0x04(%esi)
+7 L3 89 06 mov %eax -> (%esi)
+9 L3 8b c6 mov %esi -> %eax
+11 L3 5e pop %esp (%esp) -> %esi %esp
+12 L3 5d pop %esp (%esp) -> %ebp %esp
+13 L3 c2 04 00 ret $0x00000004 %esp (%esp) -> %esp
END 0x76b95b6c

I could add a suppression for plfCreateLOCALFONT, since it seems like a small leaf routine, but it's possible that it could allocate things that a user is forgetting to free.

Alternatively we could try to handle this by following pointers from mid-chunk pointers. I don't know how many false negatives that might create, though.

I'm going to suppress leaks from plfCreateLOCALFONT for now, unless anyone objects.

If anyone else could try running tests/hello.exe and searching the logs for plfCreateLOCALFONT, that would be useful information.

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

@derekbruening
Copy link
Contributor Author

From bruen...@google.com on January 04, 2012 14:28:35

I have seen reference to plfCreateLOCALFONT in two places

  1. leaks seen on calc on xp64:

28 total, here's one:

Error #29: POSSIBLE LEAK 80 direct bytes 0x0018d228-0x0018d278 + 0 indirect bytes

0 GDI32.dll!plfCreateLOCALFONT

1 GDI32.dll!CreateFontIndirectExW

2 GDI32.dll!CreateFontIndirectW

3 USER32.dll!CreateDlgFont

4 USER32.dll!InternalCreateDialog

5 USER32.dll!CreateDialogIndirectParamAorW

6 USER32.dll!CreateDialogParamW

7 InitSciCalc

8 WinMain

  1. issue [False?] leak reports on MessageBox #60 , probably the same thing as #1:

Error #3: POSSIBLE LEAK 80 direct bytes 0x00311830-0x00311880 + 688 indirect bytes
0x763d5e29 <GDI32.dll+0x15e29> GDI32.dll!plfCreateLOCALFONT
0x763d5bb0 <GDI32.dll+0x15bb0> GDI32.dll!CreateFontIndirectExW
0x763d5c63 <GDI32.dll+0x15c63> GDI32.dll!CreateFontIndirectW
0x7524cf63 <USP10.dll+0xcf63> USP10.dll!CacheFontLinkingData
0x7524d131 <USP10.dll+0xd131> USP10.dll!IsFontRegLinked
0x7524d48c <USP10.dll+0xd48c> USP10.dll!LoadFont
0x75249317 <USP10.dll+0x9317> USP10.dll!FindOrCreateFaceCache
0x75249630 <USP10.dll+0x9630> USP10.dll!FindOrCreateSizeCacheWithoutRealizationID
0x752499bb <USP10.dll+0x99bb> USP10.dll!FindOrCreateSizeCacheUsingRealizationID
0x7524a528 <USP10.dll+0xa528> USP10.dll!UpdateCache
0x7524a692 <USP10.dll+0xa692> USP10.dll!ScriptCheckCache
0x75247928 <USP10.dll+0x7928> USP10.dll!ScriptStringAnalyse

@derekbruening
Copy link
Contributor Author

From rnk@google.com on January 10, 2012 12:33:41

Fixed in r696 .

@derekbruening
Copy link
Contributor Author

From rnk@google.com on January 27, 2012 11:32:19

Should say "suppessed in r696 ". It would be interesting to implement something to interpret this backwards linked list in an array as reachable.

Labels: -Priority-Medium Priority-Low

@derekbruening
Copy link
Contributor Author

From bruen...@google.com on May 13, 2013 10:56:38

A win8 app_suite_tests Msgbox leak looks similar to the one here so I'm going to expand that suppression:

Error #1: POSSIBLE LEAK 80 direct bytes 0x03534a30-0x03534a80 + 688 indirect bytes

0 replace_RtlAllocateHeap+0x0 [c:\derek\drmemory\git\src\common\alloc_replace.c:2878](0x02b75ff0 <drmemorylib.dll+0x175ff0)

1 GDI32.dll!CreateFontIndirectExW+0x152 (0x7666018e <GDI32.dll+0x5018e>)

2 GDI32.dll!CreateFontIndirectW+0x5e (0x7666013e <GDI32.dll+0x5013e>)

3 GDI32.dll!CacheFontLinkingData+0x212 (0x7662e310 <GDI32.dll+0x1e310>)

4 GDI32.dll!IsFontRegLinked+0x23 (0x7662df89 <GDI32.dll+0x1df89>)

5 GDI32.dll!LoadFont +0x3a93 (0x7662e0dd <GDI32.dll+0x1e0dd>)

6 GDI32.dll!FindOrCreateFaceCache+0xb92 (0x7662a625 <GDI32.dll+0x1a625>)

7 GDI32.dll!FindOrCreateSizeCacheWithoutRealizationID+0x75 (0x766292e5 <GDI32.dll+0x192e5>)

8 GDI32.dll!FindOrCreateSizeCacheUsingRealizationID+0x8f58 (0x7662924d <GDI32.dll+0x1924d>)

9 GDI32.dll!UpdateCache+0x2c (0x766203ef <GDI32.dll+0x103ef>)

#10 GDI32.dll!ScriptCheckCache+0x526e (0x766203a8 <GDI32.dll+0x103a8>)
#11 GDI32.dll!ScriptStringAnalyse+0x12e (0x766211b3 <GDI32.dll+0x111b3>)

Owner: ---

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

No branches or pull requests

1 participant