opencv / opencv_contrib

Repository for OpenCV's extra modules
Apache License 2.0
9.31k stars 5.74k forks source link

We chat QR Scan crashes with certain images. #3150

Closed rafaelRinconFo closed 11 hours ago

rafaelRinconFo commented 2 years ago
System information (version)
Detailed description

I've implemented the WeChat QR Code Scanner in a similar fashion to the one included in guides such as this one and this one (C++ implementations). The QR scanner seems to work in general, but we have noticed occasions where the process just crashes silently. After launching the script in debugging mod we have cached the following errors:

Object "/usr/local/lib/libopencv_wechat_qrcode.so.4.5", at 0x7fae230675ca, in cv::wechat_qrcode::WeChatQRCode::detectAndDecode[abi:cxx11](cv::_InputArray const&, cv::_OutputArray const&)

Object "/usr/local/lib/libopencv_wechat_qrcode.so.4.5", at 0x7fae23066fdb, in cv::wechat_qrcode::WeChatQRCode::Impl::decode[abi:cxx11](cv::Mat const&, std::vector<cv::Mat, std::allocator<cv::Mat> >&, std::vector<cv::Mat, std::allocator<cv::Mat> >&)

Thread 1 "qr_scan" received signal SIGSEGV, Segmentation fault. 0x00007ffff7cc1097 in zxing::qrcode::Detector::sizeOfBlackWhiteBlackRun(int, int, int, int) () from target:/usr/local/lib/libopencv_wechat_qrcode.so.4.5

Steps to reproduce

For reproducing, you can use the scanner method detectAndDecode with the following image. We have found that this image manages to crash the scanner: aiuda

levent2100 commented 2 years ago

i have the same experience some image which crashing in one version such as opencv 4.5.5 => does not crash in other version 4.5.2 and same code dont crash under windows but crash in linux compile.

in my opinion opencv build options matter here

Thread 1 received signal SIGSEGV, Segmentation fault. 0x00007ffff52a150d in zxing::qrcode::Detector::sizeOfBlackWhiteBlackRun(int, int, int, int) () from /usr/local/lib/libopencv_wechat_qrcode.so.4.5 (gdb) where

0 0x00007ffff52a150d in zxing::qrcode::Detector::sizeOfBlackWhiteBlackRun(int, int, int, int) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

1 0x00007ffff52a165f in zxing::qrcode::Detector::sizeOfBlackWhiteBlackRunBothWays(int, int, int, int, int, bool) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

2 0x00007ffff52a194a in zxing::qrcode::Detector::calculateModuleSizeOneWay(zxing::Ref, zxing::Ref, int, int) ()

at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

3 0x00007ffff52a5257 in zxing::qrcode::Detector::processFinderPatternInfo(zxing::Ref, zxing::ErrorHandler&) ()

at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

4 0x00007ffff52a75f6 in zxing::qrcode::Detector::getPossibleAlignmentCount(int) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

5 0x00007ffff52b9212 in zxing::qrcode::QRCodeReader::decodeMore(zxing::Ref, zxing::Ref, zxing::DecodeHints, zxing::ErrorHandler&) ()

at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

6 0x00007ffff52bbda1 in zxing::qrcode::QRCodeReader::decode(zxing::Ref, zxing::DecodeHints) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

7 0x00007ffff527ab14 in cv::wechat_qrcode::DecoderMgr::Decode(zxing::Ref, zxing::DecodeHints) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

8 0x00007ffff527acb4 in cv::wechat_qrcode::DecoderMgr::TryDecode(zxing::Ref, zxing::Ref&) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

9 0x00007ffff527b167 in cv::wechat_qrcode::DecoderMgr::decodeImage(cv::Mat, bool, std::__cxx11::basic_string<char, std::char_traits, std::allocator >&) ()

at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

10 0x00007ffff527f158 in cv::wechat_qrcode::WeChatQRCode::Impl::decode[abi:cxx11](cv::Mat const&, std::vector<cv::Mat, std::allocator >&, std::vector<cv::Mat, std::allocator >&) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

11 0x00007ffff527f850 in cv::wechat_qrcode::WeChatQRCode::detectAndDecode[abi:cxx11](cv::_InputArray const&, cv::_OutputArray const&) () at /usr/local/lib/libopencv_wechat_qrcode.so.4.5

....

img377

img77

levent2100 commented 2 years ago

FYI if you compile opencv just without any other options like below, without TBB without openGL etc... it works for me, crashing images works normal

cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.5.2/modules \ ../opencv-4.5.2

rafaelRinconFo commented 2 years ago

Thank you for the advice, it could be a temporary workaround, however we need to compile several flags for our applications.

alalek commented 2 years ago

/cc @dddzg

rafaelRinconFo commented 2 years ago

Just in order to let you know, these are the flags we are using. Version is 4.5.4 as I've stated before.

    # ------------------------------
    && cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D WITH_CUDA=ON \
    -D WITH_CUBLAS=ON \ 
    -D CUDA_FAST_MATH=1 \
    -D WITH_GSTREAMER=ON \
    -D WITH_OPENGL=ON \
    -D CUDA_ARCH_BIN=${ARCH_BIN} \
    -D CUDA_ARCH_PTX="" \
    -D CUDA_NVCC_FLAGS="--expt-relaxed-constexpr" \
    -D BUILD_opencv_cudacodec=ON \
    -D WITH_V4L=ON \    
    -D WITH_TBB=ON \
    -D ENABLE_FAST_MATH=1 \        
    -D WITH_QT=OFF \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D INSTALL_C_EXAMPLES=OFF \
    -D INSTALL_PYTHON_EXAMPLES=OFF \
    -D OPENCV_GENERATE_PKGCONFIG=ON \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_build/opencv_contrib/modules \
    -D BUILD_EXAMPLES=OFF ..  \
peters commented 2 years ago

@alalek I managed to reproduce this crash is on my dev machine. Using the latest git commit from https://github.com/opencv/opencv/commit/b2e20a82ba27615a2e55325ed973d3e5ee5b6778 and https://github.com/opencv/opencv_contrib/commit/3b5a55876fe0502418a9d9fb7d388c40f2a626b1 the demo crashes immediately if compiled with -DENABLE_FAST_MATH=ON. Pretty much any image you try will reproduce the crash.

asmorkalov commented 1 year ago

I was able to reproduce the issue with current 4.x (pre-4.8.0) with Fast Math option enabled in debug mode only. Release works well. Stack is corrupted:

Thread 1 "test" received signal SIGSEGV, Segmentation fault.
0x00007ffff7b55997 in zxing::BitMatrix::get (this=0x555555d4c280, x=-2147483648, y=115) at /home/alexander/Projects/OpenCV/opencv_contrib/modules/wechat_qrcode/src/zxing/common/bitmatrix.hpp:56
56          unsigned char get(int x, int y) const { return bits[width * y + x]; }

and the proposed patch with Nans does not fix it, but hides something else.

asmorkalov commented 1 year ago

With fast-math option compiler expects that floats could not be NaNs and makes related optimizations. Discussion on stackoverflow: https://stackoverflow.com/questions/69463347/why-does-gcc-ffast-math-disable-the-correct-result-of-isnan-and-isinf GCC issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949 It looks like the right way to fix the Zxing library is not to return nan in detector.cpp:495, but return dedicated boolean status. IsNan is not needed any more. Other trials to handle nans with -fast-math will lead to sparadic issues that are compiler dependant.

opencv-alalek commented 1 year ago

To avoid SIGSEGV need to add checks for input values in methods which access arrays (like Detector::sizeOfBlackWhiteBlackRun, check for points inside of image rectangle)