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

test_stroke segfault #4156

Closed
hugovk opened this issue Oct 21, 2019 · 2 comments · Fixed by #4160
Closed

test_stroke segfault #4156

hugovk opened this issue Oct 21, 2019 · 2 comments · Fixed by #4160
Labels
Bug Any unexpected behavior, until confirmed feature. Windows
Projects

Comments

@hugovk
Copy link
Member

hugovk commented Oct 21, 2019

What did you do?

Run tests on Windows.

(Found by @cgohlke at #4152 (comment))

What did you expect to happen?

No segfault.

What actually happened?

A segfault in test_imagedraw.py::TestImageDraw::test_stroke on all platforms, e.g.:

=============================================================== test session starts ================================================================
platform win32 -- Python 3.8.0, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- X:\Python38\python.exe
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('D:\\Build\\Pillow\\Pillow-6.2.1\\.hypothesis\\examples')
rootdir: D:\Build\Pillow\Pillow-6.2.1, inifile: setup.cfg
plugins: hypothesis-4.40.0, palladium-1.2.2, cov-2.8.1, forked-1.1.1, xdist-1.30.0
collected 1380 items
<snip>
Tests/test_imagedraw.py::TestImageDraw::test_stroke Windows fatal exception: access violation

Current thread 0x00003724 (most recent call first):
  File "X:\Python38\lib\site-packages\PIL\ImageFont.py", line 466 in getmask2
  File "X:\Python38\lib\site-packages\PIL\ImageDraw.py", line 309 in draw_text
  File "X:\Python38\lib\site-packages\PIL\ImageDraw.py", line 346 in text
  File "D:\Build\Pillow\Pillow-6.2.1\Tests\test_imagedraw.py", line 828 in test_stroke
  File "X:\Python38\lib\unittest\case.py", line 633 in _callTestMethod
  File "X:\Python38\lib\unittest\case.py", line 676 in run
  File "D:\Build\Pillow\Pillow-6.2.1\Tests\helper.py", line 61 in run
  File "X:\Python38\lib\unittest\case.py", line 736 in __call__
  File "X:\Python38\lib\site-packages\_pytest\unittest.py", line 207 in runtest
  File "X:\Python38\lib\site-packages\_pytest\runner.py", line 125 in pytest_runtest_call
  File "X:\Python38\lib\site-packages\pluggy\callers.py", line 187 in _multicall
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 83 in <lambda>
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 92 in _hookexec
  File "X:\Python38\lib\site-packages\pluggy\hooks.py", line 286 in __call__
  File "X:\Python38\lib\site-packages\_pytest\runner.py", line 201 in <lambda>
  File "X:\Python38\lib\site-packages\_pytest\runner.py", line 229 in from_call
  File "X:\Python38\lib\site-packages\_pytest\runner.py", line 200 in call_runtest_hook
  File "X:\Python38\lib\site-packages\_pytest\runner.py", line 176 in call_and_report
  File "X:\Python38\lib\site-packages\_pytest\runner.py", line 95 in runtestprotocol
  File "X:\Python38\lib\site-packages\_pytest\runner.py", line 80 in pytest_runtest_protocol
  File "X:\Python38\lib\site-packages\pluggy\callers.py", line 187 in _multicall
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 83 in <lambda>
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 92 in _hookexec
  File "X:\Python38\lib\site-packages\pluggy\hooks.py", line 286 in __call__
  File "X:\Python38\lib\site-packages\_pytest\main.py", line 256 in pytest_runtestloop
  File "X:\Python38\lib\site-packages\pluggy\callers.py", line 187 in _multicall
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 83 in <lambda>
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 92 in _hookexec
  File "X:\Python38\lib\site-packages\pluggy\hooks.py", line 286 in __call__
  File "X:\Python38\lib\site-packages\_pytest\main.py", line 235 in _main
  File "X:\Python38\lib\site-packages\_pytest\main.py", line 191 in wrap_session
  File "X:\Python38\lib\site-packages\_pytest\main.py", line 228 in pytest_cmdline_main
  File "X:\Python38\lib\site-packages\pluggy\callers.py", line 187 in _multicall
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 83 in <lambda>
  File "X:\Python38\lib\site-packages\pluggy\manager.py", line 92 in _hookexec
  File "X:\Python38\lib\site-packages\pluggy\hooks.py", line 286 in __call__
  File "X:\Python38\lib\site-packages\_pytest\config\__init__.py", line 90 in main
  File "X:\Python38\lib\site-packages\pytest.py", line 101 in <module>
  File "X:\Python38\lib\runpy.py", line 85 in _run_code
  File "X:\Python38\lib\runpy.py", line 192 in _run_module_as_main

What are your OS, Python and Pillow versions?

  • OS: Windows
  • Python: all
  • Pillow: 6.2.0, 6.2.1

I noticed the crash first with Python 2,7 32-bit but can reproduce it on all Python versions and also with Pillow 6.2.0 when turning on Heap Verification.

More info

Crash is at https://github.com/python-pillow/Pillow/blob/6.2.x/src/_imagingft.c#L947. source is invalid.

>	_imagingft.cp38-win_amd64.pyd!font_render(FontObject * self, _object * args) Line 947	C
 	python38.dll!method_vectorcall_VARARGS(_object * func, _object * const * args, unsigned __int64 nargsf, _object * kwnames) Line 301	C
 	[Inline Frame] python38.dll!_PyObject_Vectorcall(_object * nargsf, _object * const *) Line 127	C
 	python38.dll!call_function(_ts * tstate, _object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4987	C
 	python38.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3487	C
 	[Inline Frame] python38.dll!PyEval_EvalFrameEx(_frame *) Line 741	C
 	python38.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * const * args, __int64 argcount, _object * const * kwnames, _object * const * kwargs, __int64 kwcount, int kwstep, _object * const * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4298	C
 	python38.dll!_PyFunction_Vectorcall(_object * func, _object * const * stack, unsigned __int64 nargsf, _object * kwnames) Line 435	C
 	[Inline Frame] python38.dll!_PyObject_Vectorcall(_object * nargsf, _object * const *) Line 127	C
 	python38.dll!method_vectorcall(_object * method, _object * const * args, unsigned __int64 nargsf, _object * kwnames) Line 89	C
 	python38.dll!PyVectorcall_Call(_object * callable, _object * tuple, _object * kwargs) Line 199	C
 	[Inline Frame] python38.dll!PyObject_Call(_object *) Line 227	C
 	python38.dll!do_call_core(_ts * tstate, _object * func, _object * callargs, _object * kwdict) Line 5034	C
 	python38.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3560	C
 	[Inline Frame] python38.dll!PyEval_EvalFrameEx(_frame *) Line 741	C
 	python38.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * const * args, __int64 argcount, _object * const * kwnames, _object * const * kwargs, __int64 kwcount, int kwstep, _object * const * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4298	C
 	[Inline Frame] python38.dll!_PyFunction_Vectorcall(_object * stack, _object * const *) Line 435	C
 	[Inline Frame] python38.dll!_PyObject_Vectorcall(_object * nargsf, _object * const *) Line 127	C
 	python38.dll!call_function(_ts * tstate, _object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4987	C
 	python38.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3501	C
 	[Inline Frame] python38.dll!PyEval_EvalFrameEx(_frame *) Line 741	C
 	python38.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * const * args, __int64 argcount, _object * const * kwnames, _object * const * kwargs, __int64 kwcount, int kwstep, _object * const * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4298	C
 	[Inline Frame] python38.dll!_PyFunction_Vectorcall(_object * stack, _object * const *) Line 435	C
 	[Inline Frame] python38.dll!_PyObject_Vectorcall(_object *) Line 127	C
 	python38.dll!method_vectorcall(_object * method, _object * const * args, unsigned __int64 nargsf, _object * kwnames) Line 60	C
 	[Inline Frame] python38.dll!_PyObject_Vectorcall(_object * nargsf, _object * const *) Line 127	C
 	python38.dll!call_function(_ts * tstate, _object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4987	C
 	python38.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3516	C
 	[Inline Frame] python38.dll!PyEval_EvalFrameEx(_frame *) Line 741	C
 	python38.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * const * args, __int64 argcount, _object * const * kwnames, _object * const * kwargs, __int64 kwcount, int kwstep, _object * const * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4298	C
 	python38.dll!PyEval_EvalCodeEx(_object * _co, _object * globals, _object * locals, _object * const * args, int argcount, _object * const * kws, int kwcount, _object * const * defs, int defcount, _object * kwdefs, _object * closure) Line 4334	C
 	python38.dll!PyEval_EvalCode(_object * co, _object * globals, _object * locals) Line 724	C
 	python38.dll!run_eval_code_obj(PyCodeObject * co, _object * globals, _object * locals) Line 1117	C
 	python38.dll!run_mod(_mod * mod, _object * filename, _object * globals, _object * locals, PyCompilerFlags * flags, _arena * arena) Line 1140	C
 	python38.dll!PyRun_FileExFlags(_iobuf * fp, const char * filename_str, int start, _object * globals, _object * locals, int closeit, PyCompilerFlags * flags) Line 1055	C
 	python38.dll!PyRun_SimpleFileExFlags(_iobuf * fp, const char * filename, int closeit, PyCompilerFlags * flags) Line 431	C
 	python38.dll!PyRun_AnyFileExFlags(_iobuf * fp, const char * filename, int closeit, PyCompilerFlags * flags) Line 87	C
 	python38.dll!pymain_run_file(PyConfig * config, PyCompilerFlags * cf) Line 381	C
 	python38.dll!pymain_run_python(int * exitcode) Line 566	C
 	python38.dll!Py_RunMain() Line 646	C
 	python38.dll!Py_Main(int argc, wchar_t * * argv) Line 687	C

  | Name | Value | Type
-- | -- | -- | --
▶ | args | 0x000002e52700de20 {ob_refcnt=1 ob_type=0x00007ffd394234d0 {python38.dll!_typeobject PyTuple_Type} {...} } | _object *
  | ascender | 0 | int
▶ | bitmap | {rows=72 width=74 pitch=74 ...} | FT_Bitmap_
▶ | bitmap_glyph | 0x000002e528837fb0 {root={library=??? clazz=??? format=??? ...} left=??? top=??? ...} | FT_BitmapGlyphRec_ *
  | bitmap_y | 0 | unsigned int
  | count | 1 | unsigned __int64
▶ | dir | 0x0000000000000000 <NULL> | const char *
  | error | 0 | int
▶ | features | 0x00007ffd39421880 {python38.dll!_object _Py_NoneStruct} {ob_refcnt=5862 ob_type=0x00007ffd39421a30 {python38.dll!_typeobject _PyNone_Type} {...} } | _object *
▶ | glyph | 0x000002e528837fb0 {library=??? clazz=??? format=??? ...} | FT_GlyphRec_ *
▶ | glyph_info | 0x000002e527231c10 {index=36 x_offset=0 x_advance=4608 ...} | GlyphInfo *
▶ | glyph_slot | 0x000002e528798f00 {library=0x000002e5284f6e80 {...} face=0x000002e528719b20 {num_faces=1 face_index=...} ...} | FT_GlyphSlotRec_ *
  | horizontal_dir | 1 | int
  | i | 0 | unsigned __int64
  | id | 3183250128800 | __int64
▶ | im | 0x000002e5287e3fa0 {mode=0x000002e5287e3fa0 "L" type=0 depth=0 ...} | ImagingMemoryInstance *
  | index | 36 | int
  | k | 0 | int
▶ | lang | 0x0000000000000000 <NULL> | const char *
  | left | -1 | int
  | load_flags | 8 | int
  | mask | 0 | int
▶ | self | 0x000002e5270b21b0 {ob_base={ob_refcnt=2 ob_type=0x00007ffd42b16360 {_imagingft.cp38-win_amd64.pyd!_typeobject Font_Type} {...} } ...} | FontObject *
▶ | source | 0x000002e528839b30 <Error reading characters of string.> | unsigned char *
▶ | string | 0x000002e524e6eeb0 {ob_refcnt=29 ob_type=0x00007ffd39423cf0 {python38.dll!_typeobject PyUnicode_Type} {...} } | _object *
  | stroke_width | 2 | int
  | stroker | 0x000002e5287f3f50 {...} | FT_StrokerRec_ *
▶ | target | 0x000002e5287e9aa1 "" | unsigned char *
  | temp | 0 | int
  | x | 0 | int
  | x0 | 0 | int
  | x1 | 74 | int
  | xx | 1 | int
  | y | 0 | unsigned int
  | yy | 0 | int
@hugovk hugovk added Windows Bug Any unexpected behavior, until confirmed feature. labels Oct 21, 2019
@hugovk hugovk added this to New Issues in Pillow via automation Oct 21, 2019
@cgohlke
Copy link
Contributor

cgohlke commented Oct 21, 2019

This code crashes:

from PIL import Image, ImageDraw, ImageFont

im = Image.new("RGB", (120, 130))
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("FreeMono.ttf", 120)
draw.text((10, 10), "A", "#f00", font, stroke_width=2, stroke_fill=None)

@cgohlke
Copy link
Contributor

cgohlke commented Oct 21, 2019

The issue could be that FT_Done_Glyph is called while a pointer to the bitmap is still used...

Pillow automation moved this from New Issues to Closed Nov 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Any unexpected behavior, until confirmed feature. Windows
Projects
Pillow
  
Closed
Development

Successfully merging a pull request may close this issue.

2 participants