Hey folks,
I'm currently debugging a memory leak in mitmproxy which I think is rooted somewhere outside of our codebase. In short:
- We see a slow but unbounded (heap) memory increase in long-running mitmdump sessions.
len(gc.get_objects())
is constant over time.
- When dumping the heap of a process that has accumulated a lot of memory, I see lots of certificate-related strings and lots of
_lib.c
[^1].
cat heap.bin | strings | sort | uniq -c | sort -r
37667 _lib.c
28694 B0@0
11262 DigiCert Inc1
8233 QuoVadis Limited1
7636 c0a0
7621 www.digicert.com1 0
7160 digicert inc1
6348 www.digicert.com1$0"
6207 GlobalSign
6206 GlobalSign1
5598 Amazon1
5509 Google Trust Services LLC1
5508 US1"0
5331 Salford1
5328 Greater Manchester1
5070 Texas1
5066 Houston1
4404 h&(z[
4331 globalsign1
4227 Panama1
4121 Arizona1
4040 quovadis limited1
4006 GlobalSign nv-sa1
3854 Entrust, Inc.1(0&
3853 See www.entrust.net/legal-terms1907
3829 Illinois1
3827 Chicago1!0
3799 TrustCor Certificate Authority1
3797 Panama City1$0"
3796 TrustCor Systems S. de R.L.1'0%
3624 Budapest1
3606 houston1
3601 DigiCert Inc
3564 AffirmTrust1
3495 Starfield Technologies, Inc.1200
3490 salford1
3489 www.digicert.com
3459 google trust services llc1
3449 globalsign
3434 texas1
3409 greater manchester1
3405 .1.1
3345 Dhimyotis1
3332 US1!0
3321 amazon1
3315 GlobalSign0
3183 us1"0
3139 130801120000Z
2993 nykiad
2827 Scottsdale1%0#
2767 The USERTRUST Network1.0,
2767 New Jersey1
2767 Jersey City1
2744 Root CA1
2652 WISeKey1"0
2651 trustcor certificate authority1
2650 panama city1$0"
2650 OISTE Foundation Endorsed1(0&
2647 trustcor systems s. de r.l.1'0%
2636 US1 0
2633 SecureTrust Corporation1
2612 0000Z
2610 chicago1!0
2601 TAIWAN-CA1
2576 arizona1
2573 budapest1
2571 SSL Corporation110/
2552 COMODO CA Limited1+0)
2552 Hong Kong1
2547 DE1+0)
2545 T-Systems Trust Center1%0#
2544 "T-Systems Enterprise Services GmbH1
2536 0L1 0
2531 5959Z
2511 see www.entrust.net/legal-terms1907
2508 Trustwave Holdings, Inc.1:08
2506 emSign PKI1
2484 globalsign nv-sa1
2483 illinois1
2479 ;Hellenic Academic and Research Institutions Cert. Authority1@0>
2473 180218183000Z
2470 Hongkong Post1 0
2462 160622000000Z
2453 150526000000Z
2452 panama1
2452 PL1"0
2448 Unizeto Technologies S.A.1'0%
2446 Buypass AS-9831633271 0
2434 emSign PKI1%0#
2388 PL1!0
2387 Certum Certification Authority1
2386 Asseco Data Systems S.A.1'0%
2377 Athens1D0B
2362 Microsoft Corporation1604
2350 FNMT-RCM1
2341 affirmtrust1
2257 US1%0#
2243 ertification Authority
2234 entrust, inc.1(0&
2172 .1&0$
2168 0002 481463081000361
2138 www.digicert.com1!0
2137 im Teknolojileri ve Hizmetleri A.
2121 Inc
2104 www.digicert.com1+0)
2086 The Go Daddy Group, Inc.110/
2080 QuoVadis Limited
2054 www.xrampsecurity.com1$0"
2049 %bw+s
2002 061110000000Z
1910 Amazon
1859 oiste foundation endorsed1(0&
1858 wisekey1"0
1840 090901000000Z
1830 scottsdale1%0#
1796 Google Trust Services LLC
1783 ssl corporation110/
1776 root ca1
1768 t-systems trust center1%0#
1767 starfield technologies, inc.1200
1765 G0E1
1760 securetrust corporation1
1753 certum certification authority1
1749 jersey city1
1748 the usertrust network1.0,
1738 asseco data systems s.a.1'0%
1738 Salford
1738 Greater Manchester
1736 "t-systems enterprise services gmbh1
1731 .edu0
1730 trustwave holdings, inc.1:08
1729 ;hellenic academic and research institutions cert. authority1@0>
1724 hong kong1
1723 taiwan-ca1
1719 unizeto technologies s.a.1'0%
1718 hongkong post1 0
1711 ra EBG Bili
1711 comodo ca limited1+0)
1697 dhimyotis1
1695 380118235959Z0
1695 .eu0
1694 athens1D0B
1694 .gr0
1681 emsign pki1
1677 cert.com
1676 microsoft corporation1604
1670 Certigna
1667 buypass as-9831633271 0
1665 Houston
1664 emSign PKI
[...]
./sample.py heap.bin
(random chunks from the heap)
root@memtest ~# ./sample.py heap.bin
=== 5b83400 ===
b'\r\x00\x00\x00\x17\x00\x00\x00\xa0.\xdd\x1f\x94U\x00\x00@\x00\x00\x00\x00\x0
0\x00\x00!\x00\x00\x00\x00\x00\x00\x00\x80\x15\xdd\x1f\x94U\x00\x00\x06\x00\x0
0\x00\x06\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00!\x00\x00\x00\x00\x00\x00
\x00\x01\x00\x00\x00\x02\x00\x00\x000\xff\xdc\x1f\x94U\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00!\x00\x00\x00\x00\x00\x00\x00\xd0\n\xdd\x1f\x94U\x00\x00\x01\x
00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00q\x00\x00\x00\x00\x0
0\x00\x000J1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x120\x10\x06\x03U\x04\n\x13\tI
denTrust1\'0%\x06\x03U\x04\x03\x13\x1eIdenTrust Commercial Root CA 1\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x00\x00s)\xc5\xccj\x19\xec\xecz\
xa7\xb0H\xb2\r\x1aX\xdf-7\xf4\x81Mc\xc7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf
f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff!\xef\x9cF\x91U\x00\x
00!\x00\x00\x00\x00\x00\x00\x00EC\x00\xb4g\x7f\x00\x00\x90\x04\xdd\x1f\x94U\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00
\x00\x00\x00\x00\x00\xf0e\xfc$\x94U\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x0
0\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xfe\
xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf
f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\
xc1\x00\x00\x00\x00\x00\x00\x00\x00\x830\xb2g\x7f\x00\x00P\x0f\xdd\x1f\x94U\x0
0\x00\x90\x0b\xdd\x1f\x94U\x00\x00`\x14\xdd\x1f\x94U\x00\x00\xcb\x02\x00\x00\x
01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00P\xff\xdc\x1f\x94U\x00\x00\x14\x
00\x00\x00\x00\x00\x00\x00 \x14\xdd\x1f\x94U\x00\x00\x00\x00\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x13\xd
d\x1f\x94U\x00\x00@\x13\xdd\x1f\x94U\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x
80\x16\xdd\x1f\x94U\x00\x00\x10\x00\xdd\x1f\x94U\x00\x00\x00\x00\x00\x00\x00\x
00\x00\x00\xe0\x0c\xdd\x1f\x94U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00q\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00g\x7f\x00\x00`\x07\xdd
\x1f\x94U\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\xa0\x07\xdd\x1f\x94U\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x11\x01\x00\x00\x00\x00
\x00\x00\x87\x0b\x8b\x80\x8a\x19\xb3\xf2[\x83M\\\xa3-\x8
b\x95!\x18B+N\xf2\x1d>P\xb90\x9d\xd6}\xef\xf1,H\xcb\xfa\xe0\xa6n \xfc\xa5h@\x8
2\xe9\xc6\xbb\xf1r\x02\x90\xbbD\x0c\xe5\xf7\xe7;R \xf8\xa4\xca\xeft\xaf7\x84@y
U\xe6V\xf0\xda\x92\xb2\xfc_<\x12)\xca\n\x1a\xbdG>\x90\xcb\xc9\xee8\x8er\x80\x1
b\xf0S\x8bw\x97p\x8f O\xab\xa2\xdax\xcbp(O\xa8\xe2!\xcd\xceF\x95\xd8kB;u\xf7\x
fc\x12\x8c{\xe6\x8aZ(\x7f\x00\xa5\xd5\xd7n\x90|\x82\xa2\xdf\x9c\x1cn\x18\xa9\x
cbU\xf8\xe5\x16iJb"h\xf3On\x98H\xdc\x94Eg>|\xe7R\xa0A\xc4 \xc8\xa0!\x93@!)\x92
\xdf\x0e\xce0\xa4~\xdbR\xf1\xff{ \x0c\xa6\xb3Co\x15\xc5\x16\xc0\xb6\x8638\x15k
o\xf6\xbf\x8d\xcf\xe1A\x82\x10M{\x16\xe0\x8f\xe6\xc5=\x04\xf5\xed\xff\x94b+|\x
1cU}\xff\xc1_2\xe6\x06*\xa57\x84>F\xd1\xf3x\x14\xf2\xd4\x80\xb5S\x86#\xbez\xc8
\x92>\x88;$\xa0S)\x98h\x1d\xbch\xed}I\xf4\xf10\xaf\xdd\xcc\x19\x81}\xd1f\xe1?\
xa3\xe5 #\xc0\x06\x0e\x829\x06\xf5\xceu\xba\xd3\x1a\x84\xc6\xbd\xd4\x88\xdfOxT
\x91n\xdf>\xe0\xe1B\xdd\x1e\\\xfeY\xdfb\\\xa5\x8c>6\xd72\xd0\xecJk\xeb\x05\x1d
|\xa5\x8f\x80\x19\x9bg\x8e!\x9b@\x97\x15%\xb7\x9b\xdf\x17\xb4\x8d\xa8\xe6\\\xa
f\xf8\xdd(\xaa\x81\x14\xb8~\x81{\x90\xd7U\xc4\xe5\xfb!7|\x96\xc3\xe5\x193c\xa7
U\xd4\xbf\x1dn\xdc0\xc1\xec\x13\xfe7o0\xa7\x85T\xd2!\x7f*\xbf;jF\x00zw\xa2,\xc
1-\x04\xcdN\xaa*Q\xb8\x9f*\xf6\x9f/*\xbb\xb9\xca^zu|\x06q\xc4lA\xc7F\xd6\xcb[\
xc5\x13zb\xbe\\\xe1\x96\xbdy5I{i\xd1\xd3\xd3\xf3\xc1\xdf\xf9\x7fR\x95\xcc\x9d\
x9b#\xcai7&\xb4\x93\xec\xec\x7f\xa1r\xfc\xe0\x87o\xaa\xd7\x19\xcd#\xf7\x80\xf3
K\x80\x8f\x8a\x16Q\xe6\xc1\rG$Eh\xedJ\xd9\xafk\x9f\x84\xd6,\xe4T\xcf.\xaf\x06\
x12\n5\x95>\xa82@\xb7\x001\xcfH\x8a\xc7\xe6J\n\xb9\x139\x08\xdc\x03E\x03\xe9\x
c0I=\xad\x14SDNS\xe1\x1d\x86\x9e.]|m\xa3\xee\xf0\xb2\xb8\xcdQ\x97\x07\xe3\xf56
\xe8\xe1{z\xb2\x98\xf8\xa5c1\x9a\x82\xd8\x10\xceB\xb0\x86\xca]548\xc5\x00\xbe\
xda\x18B\xd6`\x93\x16r\x9e\xba2Qw\xfa\x93\xbe\xc5\x9d\x7f\xc5\xd9\x9b\xb7\\;\x
03\x0c\x9b\xc2&@\x14/i08\x8b\xc2\xb8\x8d\xf6\xb3>\xef\x18\x82\x15\xe0\x1d\xfe\
xcfz-\xd0V\xd0\x8f\xb9j\x9e\xcd\x9ah\xb0\x08\xeeK\x0f\xfe0\xf4\xc8\x08\xc0\xa0
k"U\xe7\xda\xbd>\xc7\xb9R\xbc\xc9?\x81\xbeg\x9a\xc5\xe7\xd4 }\xa8\x81\xb0\xa4\
xca\xd3#\xbb\x8bb\nG_\x1a^&\xe8#7\x17\x17|\xb3\t(\xfd\xe9-jDS%\xef\xdf<\xe4p3\
xe6i\xf2\xe7*_\xf2\x18cqn\x9eFf\xe2\x03c\tJ\xd8\xb2\x1ci\xfc\xc0\xcc\x1bt\xad\
xd7\xc72N\xf6l\x8c@:\xaa\x14\x83"\x8c\xee\xed\x82\x93\xe3\x1e\x8b\x919lb\xe2\x
b6\xa48\xb6\x90\xe1\x1d\x82U\xb1t;3.y\xc3\xef\xfc\x154\xc1\x03P^\xe3\xf3\xb0\x
c9Y;\xac\xdd\xbe\x93\x9d\xc1z\xa8&\xde7\x079D\xf0Y((\xe1\xc71\x85Zy\xd01\x01\x
f6\xf8\xce\xb6\xa8\x81\xae\x1a%z\xff(\xa5\xe5\x0b\xe3\x13\x18\xc2h\xa5\xcc;{`+
\xbe-\xd22U\xfd\xff!oX\r/\x9d\x94J\xa5Uo\xba8T\xec\xbaP\x96\x81p\xb8\x82\xe8\x
d0r/y\xe3\xd2t#\xe0=\xf8\x82\xa5c\x89x\x1b\xfb\x14rI\xaf\x19\x04\x08[?\xcc\xc8
k\x08\xcbir\x08\x96\xf8\xeb%)\xab]\x1e\xa2\n\xc7\xbb\xbbe\xaaX\xb6E\x1c\xb8\x1
9'
root@memtest ~# ./sample.py heap.bin
=== 1c219c00 ===
b'ERTrustRSAAddTrustCA.crt0%\x06\x08+\x06\x01\x05\x05\x070\x01\x86\x19http://o
csp.usertrust.com\x1d\x7f\xdb\xbd\x9f\x00\x00\x00\x00!\x02\x00\x00\x00\x00\x00
\x000\x82\x02\n\x02\x82\x02\x01\x00\xc2\xf8\xa9?\x1b\x89\xfc<<\x04]=\x906\xb0\
x91:y\xdf\xac\xaf\xe7\xa1\x88k1\xaf\xf0\x8b\xd0\x183\xb8\xdbEj4\xf4\x0
2\x80$(\n\x02\x15\x95^v*\r\x99:\x14[\xf6\xcb\xcbS\xbc\x13M\x01\x887\x94%\x1bB\
xbc"\xd8\x8e\xa3\x96^:\xd92\xdb>\xe8\xf0\x10e\xedt\xe1/\xa7|\xaf\'4\xbb)}\x9b\
xb6\xcf\t\xc8\xe5\xd3\n\xfc\x88eet\n\xdcs\x1c\\\xcd@\xb1\x1c\xd4\xb6\x84\x8cLP
\xcfh\x8e\xa8Y\xae\xc2\'N\x82\xa25\xdd\x14\xf4\x1f\xff\xb2w\xd5\x87/\xaan}$\'\
xe7\xc6\xcb&\xe6\xe5\xfeg\x07c\xd8E\r\xdd:Ye9Xz\x92\x99r=\x9c\x84^\x88!\xb8\xd
5\xf4,\xfc\xd9pROx\xb8\xbd<+\x8b\x95\x98\xf5\xb3\xd1h\xcf \x14~L\\_\xe7\x8b\xe
5\xf55\x81\x197\xd7\x11\x08\xb7f\xbe\xd3J\xce\x83W\x00:\xc3\x81\xf8\x17\xcb\x9
26]\xd1\xa3\xd8u\x1b\xe1\x8b\'\xeazHA\xfdE\x19\x06\xad\'\x99N\xc1pG\xdd\xb5\x9
f\x81S\x12\xe5\xb1\x8cH]1C\x17\xe3\x8c\xc6zc\x96K)0N\x84Nb\x19^<\xce\x97\x90\x
a5\x7f\x01\xeb\x9d\xe0\xf8\x8b\x89\xdd%\x98=\x92\xb6~\xef\xd9\xf1QQ}-&\xc8iYa\
xe0\xacj\xb8*6\x11\x04zP\xbd2\x84\xbe/\xdcr\xd5\xd7\x1d\x16G\xe4Gf ?\xf4\x96\x
c5\xaf\x8e\x01z\xa5\x0fzd\xf5\r\x18\x87\xd9\xae\x88\xd5\xfa\x84\xc1:\xc0i(-\xf
2\rhQ\xaa\xe3\xa5w\xc6\xa4\x90\x0e\xa17\x8b1#G\xc1\t\x08\xebn\xf7x\x9b\xd7\x82
\xfc\x84 \x99I\x19\xb6\x12F\xb1\xfbEU\x16\xa9\xa3e\xac\x9c\x07\x0f\xeak\xdc\x1
f.\x06r\xec\x86\x88\x12\xe4-\xdb_\x05/\xe4\xf0\x03\xd3&3\xe7\x80\xc2\xcdB\xa1\
x174\x0b\x02\x03\x01\x00\x01\x9b\x1f\x90+?%!,.y1\x00\x00\x00\x00\x00\x00\x00\x
b8\xd7,\xb2g\x7f\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x
00\x00\x00\xa0\x98\x84#\x94U\x00\x00\x80\x00\x00\x00\x00\x00\x00\x001\x00\x00\
x00\x00\x00\x00\x00\xc0\x87\x84#\x94U\x00\x00p~F6\x94U\x00\x00\xe0\x81F6\x94U\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00O\xe4HB0c&\xcf1\x00\x00\x00\x00\x00\x00
\x00\x03\x00\x00\x00\x00\x00\x00\x00@\x8aF6\x94U\x00\x00\x00\x00\x00\x00\x04\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\xb1\x17\xb5Y\xe9w\xca!\x00\x00\
x00\x00\x00\x00\x00\x10\xcb,\xb2g\x7f\x00\x00\x80\x8fF6\x94U\x00\x00_lib.c\x00
\x00!\x00\x00\x00\x00\x00\x00\x00\x0c\x01\x00\x00\x03\x00\x00\x00\xe0u\x84#\x9
4U\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00!\x00\x00\x00\x00\x00\x00\x00`\x7fF6
\x94U\x00\x00@\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x11\x0
2\x00\x00\x00\x00\x00\x00\xe3\x02\xa5r%\xb7\xa0\x83\xa1\xa3*\xf8\xc2\x06\xa8\x
98\xcf\xfd\x9d\xc7\x0b\xb1v\x0b\x9d\xa1z\xbd=\xe8\x936[\xaa\xe3\x9c\x04\xc0"\x
de\xfaY\xc4\xdb\x8f\x81k!\x07\x9aJ\x9e\xa2\xd0e\xdc\xaaf\xcbj\xfe{T\xb1\x9f10\
x1b\xdf\xa3j#\xa8\x0cy\xe9\x0en\xa6\x1c\x9dlvTyl\xd9\xa5\x07+\xf0{\xf3\xcb\x19
k\xc7\xec\x1c\x17\xf6\xf8\xec]|u\xbb\xfc\x15~\xa6S]\xe6\xfb}2\xb6\xc2o\xd8\x0c
qY1c)_\x8cF\xdc\x16\x91\xf6M\xa0tA\xc6\xdf\xc9q\'\xfa#\x8d \x82\xa7\xa4\x8ey\x
82\x98\x8a\xc5$~@M'
root@memtest ~# ./sample.py heap.bin
=== b7ef400 ===
b'-\x00\x00\x00\x04\x00\x00\x00\x80\xd8\xa3%\x94U\x00\x00\x80\x00\x00\x00\x00\
x00\x00\x00\xc1\x00\x00\x00\x00\x00\x00\x00`\x9f\xa3%\x94U\x00\x00\xe0\x9b\xa3
%\x94U\x00\x00 \x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00m\x8e\
xe1|\x91U\x00\x00`\xd4\xa3%\x94U\x00\x00@\x00\x00\x00\x00\x00\x00\x00 \x00\x00
\x00\x00\x00\x00\x00m\x89\xe1|\x91U\x00\x00ust CA\x00\x00`\x00\x00\x00\x00\x00
\x00\x000\x00\x00\x00\x00\x00\x00\x00\xcd\xbd\xe1|\x91U\x00\x00\x00\xe8\xa3%\x
94U\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9
0\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\xdd\xc1\xe1|\x91U\x
00\x00`\xd3\xa3%\x94U\x00\x00 \xd4\xa3%\x94U\x00\x00\x00\x00\x00\x00\x00\x00\x
00\x00\x10\x11\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00}\xc1\xe1|\
x91U\x00\x00\x86#http://crl.securetrust.com/SGCA.crl\x00\x00\x00\xa0 \x00\x00\
x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00=\xb9\xf5t\x91U\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\xd0 \x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00]\xee,k\x91U\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x117\x
00\x00\x00\x00\x00\x00p\x03\x1f\x1d\x94U\x00\x00\xf0@6&\x94U\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00p\xd7\xa3%\x94U\x00\x00\
xe0\xd6\xa3%\x94U\x00\x00 \x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x0
0\x00\xdd\x8c\xe1|\x91U\x00\x00\xf0\xd6\xa3%\x94U\x00\x00`\x00\x00\x00\x00\x00
\x00\x00@\x00\x00\x00\x00\x00\x00\x00\xad\xab\xe1|\x91U\x00\x00\x00\xd8\xa3%\x
94U\x00\x00\xe0\xd8\xa3%\x94U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\xc0j\xa3%\x94U\x00\x00p\x14\xa3%\x94
U\x00\x00 \x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00=\x8d\xe1|\
x91U\x00\x004055Z\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x0
0\x00\x00]\x8c\xe1|\x91U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\
x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00]\x8f\xe1|\x91U\x00\x00p\xd5\xa3%\
x94U\x00\x00 \x01\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x8d\x98
\xe1|\x91U\x00\x00\x06\x0c\x02us1 0\x1e\x06\x03U\x04\n\x0c\x17securetrust corp
oration1\x190\x17\x06\x03U\x04\x03\x0c\x10secure global ca\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00q\x03\x00\x00\x00\x00\x00\x00`\x9a\xa3%\x9
4U\x00\x00p\x88\xa3%\x94U\x00\x00oration\x00A\x00\x00\x00\x00\x00\x00\x00\x00\
xd6\xa3%\x94U\x00\x00p\xd7\xa3%\x94U\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00!\
x00\x00\x00\x00\x00\x00\x00\xc0j\xa3%\x94U\x00\x00P\xb7\xa3%\x94U\x00\x00`\x00
\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00M\x8e\xe1|\x91U\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\xe0\xda\xa3%\x94U\x00\x00\x90\xd6\xa3%\x94U\x00
\x00J\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x00\x00\xc0j\xa3%\x94U\
x00\x00\x00\xd6\xa3%\x94U\x00\x00 \x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x0
0\x00\x00\x00\xbd\x8f\xe1|\x91U\x00\x00ust CA\x00\x00\xd0\x00\x00\x00\x00\x00\
x00\x00@\x00\x00\x00\x00\x00\x00\x00]\t\xe1|\x91U\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00'
root@memtest ~# ./sample.py heap.bin
=== 760f000 ===
b'\x05\x000A1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x140\x12\x06\x03U\x04\n\x0c\x
0bAffirmTrust1\x1c0\x1a\x06\x03U\x04\x03\x0c\x13AffirmTrust Premium0\x1e\x17\r
100129141036Z\x17\r401231141036Z0A1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x140\x1
2\x06\x03U\x04\n\x0c\x0bAffirmTrust1\x1c0\x1a\x06\x03U\x04\x03\x0c\x13AffirmTr
ust Premium0\x82\x02"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02
\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\xc4\x12\xdf\xa9_\xfeA\xdd\xdd\xf5\x9f\
x8a\xe3\xf6\xac\xe1Q\xa7\xd1"\xc4\n\xa78Hl\xb3\
xf9\xff}\xab\x86W\xe3\xba\xd6\x85xw\xbaC\xeaH\x7f\xf6\xd8\xbe#m\x1e\xbf\xd16lX
\\\xf1\xee\xa4\x19T\x1a\xf5\x03\xd2v\xe6\xe1\x8c\xbd<\xb3\xd3HK\xe2\xc8\xf8\x7
f\x92\xa8vF\x9cBe>\xa4\x1e\xc1\x07\x03ZF-\xb8\x97\xf3\xb7\xd5\xb2U!\xef\xba\xd
cL\x00\x97\xfb\x14\x95\'3\xbf\xe8CGF\xd2\x08\x99\x16`;\x9a~\xd2\xe6\xed8\xea\x
ec\x01\x1e\x10\xe5\x0b\x03\xc9\
x9aB\x00l\xc5\x94~a\xc4\x8a\xdf\x7f\x82\x1a\x0bY\xc4Y2w\xb3\xbc`iV9\xfd\xb4\x0
6{,\xd6d6\xd9\xbdH\xed\x84\x1f~\xa5"\x8f*\xb8B\xf4\x82\xb7\xd4S\x90xN-\x1a\xfd
\x81oD\xd7;\x01t\x96B\xe0\x00\xe2.k\xea\xc5\xeer\xac\xbb\xbf\xfe\xea\xaa\xa8\x
f8\xdc\xf6\xb2y\x8a\xb6g\x02\x03\x01\x00\x01\xa3B0@0\x1d\x06\x03U\x1d\x0e\x04\
x16\x04\x14\x9d\xc0g\xa6\x0c"\xd9&\xf5E\xab\xa6eR\x11\'\xd8E\xacc0\x0f\x06\x03
U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff0\x0e\x06\x03U\x1d\x0f\x01\x01\x
ff\x04\x04\x03\x02\x01\x06\x9b\x1f\x94U\x00\x00\x11\x02\x00\x00\x00\x00\x00\x0
0\xb3WM\x10bN:\xe4\xac\xea\xb8\x1c\xaf2#\xc8\xb3IZQ\x9cv(\x8dy\xaaWF\x17\xd5\x
f5R\xf6\xb7D\xe8\x08D\xbf\x18\x84\xd2\x0b\x80\xcd\xc5\x12\xfd\x00U\x05a\x87A\x
dc\xb5$\x9e<\xc4\xd8\xc8\xfbp\x9e/x\x96\x83 6\xde|\x0fi\x13\x88\xa5u6\x98\x08\
xa6\xc6\xdf\xac\xce\xe3X\xd6\xb7>\xde\xba\xf3\xeb4@\xd8\xa2\x81\xf5x?/\xd5\xa5
\xfc\xd9\xa2\xd4^\x04\x0e\x17\xad\xfeA\xf0\xe5\xb2r\xfaD\x823B\xe8-X\xf7V\x8cb
?\xbaB\xb0\x9c\x0c\\~.e&\\SO\x00\xb2x~\xa1\r\x99-\x8d\xb8\x1d\x8e\xa2\xc4\xb0\
xfd`\xd00\xa4\x8e\xc8\x04b\xa9\xc4\xed5\xdez\x97\xed\x0e8^\x92/\x93p\xa5\xa9\x
9co\xa7}\x13\x1d~\xc6\x08H\xb1^g\xebQ\x08%\xe9\xe6%kR)\x91\x9c\xd29s\x08W\xde
All these strings appear somewhere in certifi's CA bundle, so I suspected this is somehow related to us calling context.load_verify_locations(certifi.where())
. After spending quite some time on this I found https://github.com/python/cpython/issues/84904, which surprisingly reproduces with pyOpenSSL instead of stdlib:
import os
import gc
import asyncio
from OpenSSL import SSL
import certifi
import psutil
ca_path = certifi.where()
proc = psutil.Process(os.getpid())
async def make_context(sleep: bool) -> None:
ctx = SSL.Context(SSL.TLS_CLIENT_METHOD)
ctx.load_verify_locations(ca_path)
if sleep:
await asyncio.sleep(1)
async def main(n: int, sleep: bool) -> None:
await asyncio.wait([asyncio.create_task(make_context(sleep)) for _ in range(n)])
print("=== without sleep ===")
for _ in range(20):
asyncio.run(main(200, False))
gc.collect()
print(f"{proc.memory_info().rss=:>10}")
print("=== with sleep ===")
for _ in range(20):
asyncio.run(main(200, True))
gc.collect()
print(f"{proc.memory_info().rss=:>10}")
Ubuntu 22.04 Output
# python3.10 repro.py
=== without sleep ===
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
proc.memory_info().rss= 31494144
=== with sleep ===
proc.memory_info().rss= 181592064 # whoops
proc.memory_info().rss= 181862400 # but now it stays constant?
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181862400
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
proc.memory_info().rss= 181501952
Windows 10 Output
# python3.10 repro.py
=== without sleep ===
proc.memory_info().rss= 28827648
proc.memory_info().rss= 29130752
proc.memory_info().rss= 29167616
proc.memory_info().rss= 28848128
proc.memory_info().rss= 29155328
proc.memory_info().rss= 29188096
proc.memory_info().rss= 29220864
proc.memory_info().rss= 29184000
proc.memory_info().rss= 29200384
proc.memory_info().rss= 29237248
proc.memory_info().rss= 29270016
proc.memory_info().rss= 29224960
proc.memory_info().rss= 29224960
proc.memory_info().rss= 29261824
proc.memory_info().rss= 29249536
proc.memory_info().rss= 29257728
proc.memory_info().rss= 29298688
proc.memory_info().rss= 29274112
proc.memory_info().rss= 29265920
proc.memory_info().rss= 29229056
=== with sleep ===
proc.memory_info().rss= 30277632 # much better here...
proc.memory_info().rss= 31203328
proc.memory_info().rss= 32108544
proc.memory_info().rss= 31698944
proc.memory_info().rss= 31838208
proc.memory_info().rss= 31657984
proc.memory_info().rss= 75530240 # surprise!
proc.memory_info().rss= 32440320 # and we're back...
proc.memory_info().rss= 77365248 # ... up again!
proc.memory_info().rss= 77135872
proc.memory_info().rss= 81215488
proc.memory_info().rss= 79491072
proc.memory_info().rss= 78475264
proc.memory_info().rss= 78393344
proc.memory_info().rss= 32808960
proc.memory_info().rss= 86007808
proc.memory_info().rss= 82329600
proc.memory_info().rss= 83742720
proc.memory_info().rss= 87388160
proc.memory_info().rss= 90755072
proc.memory_info().rss= 89395200
proc.memory_info().rss= 98418688
proc.memory_info().rss= 87658496
proc.memory_info().rss= 95277056
proc.memory_info().rss= 97841152
proc.memory_info().rss= 97341440
proc.memory_info().rss= 96702464
proc.memory_info().rss= 99598336
proc.memory_info().rss= 98127872
proc.memory_info().rss= 100098048
proc.memory_info().rss= 103292928
proc.memory_info().rss= 94601216
proc.memory_info().rss= 95272960
proc.memory_info().rss= 96559104
proc.memory_info().rss= 93630464
proc.memory_info().rss= 99307520
proc.memory_info().rss= 102895616
proc.memory_info().rss= 99205120
proc.memory_info().rss= 106471424
proc.memory_info().rss= 102260736
proc.memory_info().rss= 31555584 # back down! maybe all fine on Windows and just GC after all?
proc.memory_info().rss= 99848192
proc.memory_info().rss= 32423936
proc.memory_info().rss= 103653376
proc.memory_info().rss= 31727616
proc.memory_info().rss= 106827776
proc.memory_info().rss= 103124992
proc.memory_info().rss= 100532224
proc.memory_info().rss= 100294656
proc.memory_info().rss= 106164224
So yeah - I'm a bit at a loss what's going on here. Any ideas? I think that the call to load_verify_locations()
may not be the actual suspect, I still see a memory increase when commenting out that line (just much less pronounced). For mitmproxy, it looks like OpenSSL 3 finally has the APIs we need to share contexts more broadly (which should alleviate the problem in our case), but independent of that it looks like something is weirdly wrong here.
[^1]: I've also no idea where _lib.c
comes from. Maybe I'm missing something, but it looks like there's no such file in either cryptography, cffi, or OpenSSL.