Bug 411536

Summary: Weird resize crash only when specific values are used
Product: [Applications] krita Reporter: Storm Engineer <storm.anthro>
Component: Resize/Scale Image/LayerAssignee: Dmitry Kazakov <dimula73>
Status: RESOLVED FIXED    
Severity: crash CC: dimula73, halla
Priority: NOR    
Version: git master (please specify the git hash!)   
Target Milestone: ---   
Platform: Arch Linux   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Storm Engineer 2019-09-02 18:29:29 UTC
I can crash Krita with 100% consistency using canvas resize and image rescale with specific values, but when I use slightly different values, it doesn't crash. More interestingly, I can reproduce in both master, and the 4.2 Alpha appimage.


STEPS TO REPRODUCE
1. Open the template file: https://www.dropbox.com/s/25s09dsxqm67gxs/1.41%5B%E2%88%9A2%5D%7C420x297mm%22A3%22%5B4962x3509px%5D.kra?dl=0
2. Resize canvas (constraint proportion UN-ticked) to 410 * 287 mm
3. Scale image (constraint proportions and adjust print separately are UN-ticked) to 584 *  410 mm

OBSERVED RESULT
Krita crashes promptly


Krita

 Version: 4.3.0-prealpha (git e96181d)
 Languages: en_US
 Hidpi: false

Qt

  Version (compiled): 5.13.0
  Version (loaded): 5.13.0

OS Information

  Build ABI: x86_64-little_endian-lp64
  Build CPU: x86_64
  CPU: x86_64
  Kernel Type: linux
  Kernel Version: 5.2.11-arch1-1-ARCH
  Pretty Productname: Arch Linux
  Product Type: arch
  Product Version: unknown


Hardware Information

  GPU Acceleration: auto
  Memory: 16006 Mb
  Number of Cores: 8
  Swap Location: /tmp

02 Sep 2019 19:41:06 +0200: Importing application/x-krita to application/x-krita. Location: /home/storm/.local/share/krita/templates/Art Templates by Storm/.source/1.41[√2]|420x297mm"A3"[4962x3509px].kra. Real location: /home/storm/.local/share/krita/templates/Art Templates by Storm/.source/1.41[√2]|420x297mm"A3"[4962x3509px].kra. Batchmode: 0
02 Sep 2019 19:41:07 +0200: Instant Preview Setting: 0
02 Sep 2019 19:41:07 +0200: Enabled stabilizer.
02 Sep 2019 19:41:07 +0200: Enabled stabilizer.
02 Sep 2019 19:41:07 +0200: Enabled stabilizer.
02 Sep 2019 19:41:07 +0200: Enabled stabilizer.
02 Sep 2019 19:41:07 +0200: Enabled stabilizer.
02 Sep 2019 19:41:07 +0200: Enabled stabilizer.
02 Sep 2019 19:41:07 +0200: Instant Preview Setting: 0
02 Sep 2019 19:41:10 +0200: Instant Preview Setting: 0
02 Sep 2019 19:42:22 +0200: ASSERT (krita): "row < 0x7FFF && col < 0x7FFF" in file /home/storm/misc/git-repos/krita/master/libs/image/tiles3/kis_tile_hash_table2.h, line 133
OpenGL Info
 
  Vendor:  "NVIDIA Corporation" 
  Renderer:  "GeForce GTX 750 Ti/PCIe/SSE2" 
  Version:  "4.6.0 NVIDIA 435.21" 
  Shading language:  "4.60 NVIDIA" 
  Requested format:  QSurfaceFormat(version 3.0, options QFlags<QSurfaceFormat::FormatOption>(DeprecatedFunctions), depthBufferSize 24, redBufferSize 8, greenBufferSize 8, blueBufferSize 8, alphaBufferSize 8, stencilBufferSize 8, samples -1, swapBehavior QSurfaceFormat::DoubleBuffer, swapInterval 0, colorSpace QSurfaceFormat::DefaultColorSpace, profile  QSurfaceFormat::CompatibilityProfile) 
  Current format:    QSurfaceFormat(version 4.6, options QFlags<QSurfaceFormat::FormatOption>(DeprecatedFunctions), depthBufferSize 24, redBufferSize 8, greenBufferSize 8, blueBufferSize 8, alphaBufferSize 8, stencilBufferSize 8, samples -1, swapBehavior QSurfaceFormat::DoubleBuffer, swapInterval 0, colorSpace QSurfaceFormat::DefaultColorSpace, profile  QSurfaceFormat::CompatibilityProfile) 
     Version: 4.6
     Supports deprecated functions true 
     is OpenGL ES: false 

QPA OpenGL Detection Info 
  supportsDesktopGL: true 
  supportsOpenGLES: true 
  isQtPreferOpenGLES: false 
== log ==
 Supported renderers: QFlags(0x2|0x4) 
Surface format preference list: 
* QSurfaceFormat(version 3.0, options QFlags<QSurfaceFormat::FormatOption>(DeprecatedFunctions), depthBufferSize 24, redBufferSize 8, greenBufferSize 8, blueBufferSize 8, alphaBufferSize 8, stencilBufferSize 8, samples -1, swapBehavior QSurfaceFormat::DoubleBuffer, swapInterval 0, colorSpace QSurfaceFormat::DefaultColorSpace, profile  QSurfaceFormat::CompatibilityProfile) 
    2 
* QSurfaceFormat(version 3.0, options QFlags<QSurfaceFormat::FormatOption>(DeprecatedFunctions), depthBufferSize 24, redBufferSize 8, greenBufferSize 8, blueBufferSize 8, alphaBufferSize 8, stencilBufferSize 8, samples -1, swapBehavior QSurfaceFormat::DoubleBuffer, swapInterval 0, colorSpace QSurfaceFormat::DefaultColorSpace, profile  QSurfaceFormat::CompatibilityProfile) 
    4 
Probing format... QSurfaceFormat::DefaultColorSpace 2 
Found format: QSurfaceFormat(version 3.0, options QFlags<QSurfaceFormat::FormatOption>(DeprecatedFunctions), depthBufferSize 24, redBufferSize 8, greenBufferSize 8, blueBufferSize 8, alphaBufferSize 8, stencilBufferSize 8, samples -1, swapBehavior QSurfaceFormat::DoubleBuffer, swapInterval 0, colorSpace QSurfaceFormat::DefaultColorSpace, profile  QSurfaceFormat::CompatibilityProfile) 
    2 
 
== end log ==
Comment 1 Storm Engineer 2019-09-02 18:41:30 UTC
New observations:
1. After doing the canvas resize, interacting with Layer 1 in any way also triggers the crash.
2. If I make a brushstroke on layer 1 before canvas resize, I'm not able to trigger the crash anymore.
Comment 2 Halla Rempt 2019-09-03 07:47:24 UTC
This is the assert: 

ASSERT (krita): "row < 0x7FFF && col < 0x7FFF" in file /home/boud/dev/krita/libs/image/tiles3/kis_tile_hash_table2.h, line 133
KCrash: crashing... crashRecursionCounter = 2
KCrash: Application Name = krita path = /home/boud/dev/i-krita/bin pid = 28237
KCrash: Arguments: /home/boud/dev/i-krita/bin/krita /home/boud/Downloads/1.41[√2]_420x297mmA3[4962x3509px].kra 
KCrash: Attempting to start /usr/lib/x86_64-linux-gnu/libexec/drkonqi from kdeinit
sock_file=/run/user/1000/kdeinit5__0
Unable to start Dr. Konqi
Re-raising signal for core dump handling.
Segmentation fault (core dumped)

This is the backtrace: 

0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff2875801 in __GI_abort () at abort.c:79
#2  0x00007ffff324af2b in QMessageLogger::fatal(char const*, ...) const ()
   from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#3  0x00007ffff4ba7858 in kis_assert_common(char const*, char const*, int, bool, bool) ()
    at /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h:208
#4  0x00007ffff4ba7c9a in kis_assert_recoverable (
    assertion=assertion@entry=0x7ffff56ef722 "row < 0x7FFF && col < 0x7FFF", 
    file=file@entry=0x7ffff56ef5e0 "/home/boud/dev/krita/libs/image/tiles3/kis_tile_hash_table2.h", 
    line=line@entry=133) at /home/boud/dev/krita/libs/global/kis_assert.cpp:106
#5  0x00007ffff5329e00 in KisTileHashTableTraits2<KisTile>::calculateHash (this=0x55556263cc40, row=33554431, 
    col=33554431) at /usr/include/c++/8/bits/atomic_base.h:295
#6  KisTileHashTableTraits2<KisTile>::getReadOnlyTileLazy (this=0x55556263cc40, col=33554431, row=33554431, 
    existingTile=@0x7fff7b7fd610: true) at /home/boud/dev/krita/libs/image/tiles3/kis_tile_hash_table2.h:379
#7  0x00007ffff534104e in KisTiledDataManager::getTile (writable=<optimized out>, row=33554431, col=33554431, 
    this=0x5555621daee0) at /home/boud/dev/krita/libs/image/tiles3/kis_tiled_data_manager.h:128
#8  KisTiledDataManager::getTilesPair (oldTile=0x5555670f0f78, tile=0x5555670f0f70, writable=<optimized out>, 
    row=33554431, col=33554431, this=0x5555621daee0)
    at /home/boud/dev/krita/libs/image/tiles3/kis_tiled_data_manager.h:107
#9  KisRandomAccessor2::fetchTileData(int, int) ()
    at /home/boud/dev/krita/libs/image/tiles3/kis_random_accessor.cc:122
#10 0x00007ffff534179a in KisRandomAccessor2::moveTo(int, int) ()
    at /home/boud/dev/krita/libs/image/tiles3/kis_random_accessor.cc:89
#11 0x00007ffff5341d23 in KisRandomAccessor2::KisRandomAccessor2(KisTiledDataManager*, int, int, int, int, bool, KisIteratorCompleteListener*) () at /home/boud/dev/krita/libs/image/tiles3/kis_random_accessor.cc:38
#12 0x00007ffff55b7c5f in KisPaintDevice::Private::KisPaintDeviceStrategy::createRandomConstAccessorNG (
    this=<optimized out>, x=-2147483648, y=-2147483648)
    at /home/boud/dev/krita/libs/image/kis_paint_device_data.h:262
#13 0x00007ffff55a538b in KisPaintDevice::createRandomConstAccessorNG (this=this@entry=0x55556263c770, 
    x=x@entry=-2147483648, y=y@entry=-2147483648) at /home/boud/dev/krita/libs/image/kis_paint_device.cc:1791
#14 0x00007ffff55b079f in Impl::calculateExactBoundsImpl<Impl::CheckFullyTransparent> (
    device=device@entry=0x55556263c770, startRect=..., endRect=..., compareOp=...)
    at /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h:372
#15 0x00007ffff55ab72b in KisPaintDevice::calculateExactBounds(bool) const ()
    at /home/boud/dev/krita/libs/image/kis_paint_device.cc:1407
#16 0x00007ffff55ae8fb in KisLockFreeCache<QRect>::getValue (this=0x55556263c8c0)
    at /usr/include/c++/8/bits/atomic_base.h:468
#17 0x00007ffff55a770a in KisPaintDeviceCache::exactBounds (this=<optimized out>)
    at /home/boud/dev/krita/libs/image/kis_paint_device_cache.h:60
#18 KisPaintDevice::exactBounds (this=<optimized out>)
    at /home/boud/dev/krita/libs/image/kis_paint_device.cc:1224
#19 0x00007ffff552cc0f in KisLayer::layerExtentImpl(bool) const ()
    at /home/boud/dev/krita/libs/image/kis_layer.cc:956
#20 0x00007ffff55c8658 in KisPaintLayer::exactBounds() const ()
    at /home/boud/dev/krita/libs/image/kis_paint_layer.cc:260
#21 0x00007fffb8f17aa3 in KisMoveBoundsCalculationJob::run() ()
    at /home/boud/dev/krita/plugins/tools/basictools/KisMoveBoundsCalculationJob.cpp:46
#22 0x00007ffff56ecc54 in non-virtual thunk to KisUpdateJobItem::run() ()
    at /usr/include/c++/8/bits/atomic_base.h:295
#23 0x00007ffff32733e2 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#24 0x00007ffff326ec72 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#25 0x00007fffec42f6db in start_thread (arg=0x7fff7b7fe700) at pthread_create.c:463
#26 0x00007ffff295688f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Comment 3 Dmitry Kazakov 2019-09-06 10:03:22 UTC
The crash looks funny, let's check it :)
Comment 4 Dmitry Kazakov 2019-09-06 10:10:48 UTC
The crash happens because the second "scale" actually scales into exactly the same pixel size. So there might be some division-by-small-value or something.
Comment 5 Dmitry Kazakov 2019-09-06 13:46:55 UTC
Git commit 0f9c5472581252a6c5e34ec912a292138d960ef8 by Dmitry Kazakov.
Committed on 06/09/2019 at 13:46.
Pushed by dkazakov into branch 'master'.

Fix crash after cropping a specific image

This patch ends the era of the custom "empty extent" value
QRect(quint32_MAX, quint32_MAX, 0, 0). When I started refactoring
tile engine ten years ago in 2009, this "empty extent" flag was
already present. It was just a result of the way how extent was
calculated those days. I guess it was also considered as
an "optimization", or as "a flag" that could ease debugging a bit
(and it actually did help debugging a couple of times).

Years passed by and I considered to remove this custom value multiple
times. It was always causing troubles, because the QRect is not safe
against integer oveflows. But the problem was, there was code outside
tiles engine that relied on this behavior. So I was always scared of
the actual removal. Even when the tile engine was rewritten again
to become lockfree in 2017, I insisted on keeping the old behavior...

So, it looks like now all code that relies on this custom value is gone,
so it should be safe to remove it.

Funny side, I guess it was one of few artifacts that were still kept
in Krita since 'tiles' and 'tiles_new' days (has anyone ever wondered
why the engine's folder is called 'tiles3'?) ;)

M  +9    -9    libs/image/tests/kis_iterator_test.cpp
M  +11   -11   libs/image/tests/kis_iterators_ng_test.cpp
M  +10   -10   libs/image/tiles3/KisTiledExtentManager.cpp
M  +14   -4    libs/image/tiles3/kis_memento.h
M  +1    -1    libs/image/tiles3/tests/kis_tiled_data_manager_test.cpp

https://invent.kde.org/kde/krita/commit/0f9c5472581252a6c5e34ec912a292138d960ef8
Comment 6 Dmitry Kazakov 2019-09-13 09:59:55 UTC
Git commit 9be377ae3fe84d8baa1cfa11b95dfdcc5adf4d33 by Dmitry Kazakov.
Committed on 13/09/2019 at 09:00.
Pushed by dkazakov into branch 'krita/4.2'.

Fix crash after cropping a specific image

This patch ends the era of the custom "empty extent" value
QRect(quint32_MAX, quint32_MAX, 0, 0). When I started refactoring
tile engine ten years ago in 2009, this "empty extent" flag was
already present. It was just a result of the way how extent was
calculated those days. I guess it was also considered as
an "optimization", or as "a flag" that could ease debugging a bit
(and it actually did help debugging a couple of times).

Years passed by and I considered to remove this custom value multiple
times. It was always causing troubles, because the QRect is not safe
against integer oveflows. But the problem was, there was code outside
tiles engine that relied on this behavior. So I was always scared of
the actual removal. Even when the tile engine was rewritten again
to become lockfree in 2017, I insisted on keeping the old behavior...

So, it looks like now all code that relies on this custom value is gone,
so it should be safe to remove it.

Funny side, I guess it was one of few artifacts that were still kept
in Krita since 'tiles' and 'tiles_new' days (has anyone ever wondered
why the engine's folder is called 'tiles3'?) ;)

M  +9    -9    libs/image/tests/kis_iterator_test.cpp
M  +11   -11   libs/image/tests/kis_iterators_ng_test.cpp
M  +10   -10   libs/image/tiles3/KisTiledExtentManager.cpp
M  +14   -4    libs/image/tiles3/kis_memento.h
M  +1    -1    libs/image/tiles3/tests/kis_tiled_data_manager_test.cpp

https://invent.kde.org/kde/krita/commit/9be377ae3fe84d8baa1cfa11b95dfdcc5adf4d33