8000 Possible memory violation in sf::Texture::loadFromImage · Issue #3345 · SFML/SFML · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Possible memory violation in sf::Texture::loadFromImage #3345

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

Closed
3 tasks done
viencent2 opened this issue Dec 11, 2024 · 9 comments
Closed
3 tasks done

Possible memory violation in sf::Texture::loadFromImage #3345

viencent2 opened this issue Dec 11, 2024 · 9 comments
Labels

Comments

@viencent2
Copy link

Prerequisite Checklist

Describe your issue here

bool sf::Texture::loadFromImage ( const Image & image, const IntRect & area = IntRect() )

I am running the build with thread sanitizer and I have reason to believe that this function violates the memory if area goes out of bounds. As I get sanitizer issue 100% of a time after I call this function.

Here I have an image. with the size 3750 x 150
and I load animation frames into textures of 150 x 150

if (!tex->loadFromImage(image, false, sf::IntRect(sf::Vector2((int)(0 + x), 0), sf::Vector2((int)_w, (int)_w))))
            throw gui::exception() << "ResourcesSFML::_loadTextures:: Failed to load texture: " + _path.string();
loading starts
image size 3750 x 150
load 0 to 150
...
load 3600 to 3750

So if I change IntRect to be (x, 0) (_w - 1, _w -1) I get no sanitizer issue. So I assume there still was some memory violation trying to load from image on the bounds.

Here is the sanitizer issue:

WARNING: ThreadSanitizer: data race (pid=7816)
  Write of size 8 at 0x729400009948 by main thread (mutexes: write M0):
    #0 memset ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:87 (libtsan.so.2+0x8ba90) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 memset ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:85 (libtsan.so.2+0x8ba90)
    #2 <null> <null> (iris_dri.so+0xcba1ec) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #3 _loadAnimatedSprite(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ResourceOptions const&) Resources.cpp:16 (SFML+0x5ded9a)

  Previous write of size 8 at 0x729400009948 by thread T4:
    #0 memset ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:87 (libtsan.so.2+0x8ba90) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 memset ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:85 (libtsan.so.2+0x8ba90)
    #2 <null> <null> (iris_dri.so+0xcba1ec) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)

Your Environment

  • OS / distro / window manager: Ubuntu 24
  • SFML version: d4ee28c
  • Compiler / toolchain: GCC 14 / CLANG
  • Special compiler / CMake flags: -fsanitize=thread

Steps to reproduce

Sorry I don't have time to produce the minimum example. Also the issue is not easy to trigger as it requires some memory work after the function under sanitizer mode to even notice the problem.

But generally just load a bunch of images with this function

std::vector<spSfmlTexture> textures;
sf::Image image = load(_path);
for (size_t x = 0; x < image.getSize().x; x += _w)
    {
        std::shared_pointer<sf::Texture> tex = std::make_shared<sf::Texture>();
        tex->setSmooth(true);
        if (!tex->loadFromImage(image, false, sf::IntRect(sf::Vector2((int)(0 + x), 0), sf::Vector2((int)_w, (int)_w))))
            throw 1;
        textures.emplace_back(tex);
    }
return textures;

Expected behavior

No Sanitizer issues

Actual behavior

Sanitizer report memory access data race after loading textures from image class at exact image bounds.

@viencent2 viencent2 added the bug label Dec 11, 2024
@eXpl0it3r
Copy link
Member

What's _w and _h in your case?

@viencent2
Copy link
Author

there is no _h. it is 150x150 only _w. the image size 3750 x 150
I am debugging now sanitizer issues and have one more, maybe that other one causes this to happen. will investigate.

@viencent2
Copy link
Author
viencent2 commented Dec 11, 2024

actually it can be a broader issue. here is the min example

int main()
{
    sf::RenderWindow window(sf::VideoMode(sf::Vector2u(1700, 800)),
                     "SFML works!",
                     sf::Style::Default,
                     sf::State::Windowed,
                     {.antiAliasingLevel = 8});
    while (window.isOpen()) {
        while (auto ev = window.pollEvent()) {
            if (ev->is<sf::Event::Closed>())
                window.close();
        }
        window.clear(sf::Color::Black);
        window.display();
    }

I link with

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(SFML_SUFFIX "-d")
else()
    set(SFML_SUFFIX "")
endif()

find_package(X11 REQUIRED)
find_package(Freetype REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE
    ${SFML_LIBRARY_DIR}/libsfml-graphics${SFML_SUFFIX}.so
    ${SFML_LIBRARY_DIR}/libsfml-window${SFML_SUFFIX}.so
    ${SFML_LIBRARY_DIR}/libsfml-system${SFML_SUFFIX}.so
    ${FREETYPE_LIBRARIES}
    udev
    ${X11_LIBRARIES}
    Xi
    Xrandr
    Xcursor
 )
-fsanitize=thread

on Ubuntu24 and it seems to always data race with iris driver

==================
WARNING: ThreadSanitizer: data race (pid=140091)
  Write of size 8 at 0x722c00005800 by main thread (mutexes: write M0, write M1):
    #0 free ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:724 (libtsan.so.2+0x57c71) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 <null> <null> (iris_dri.so+0xf5282) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #2 <null> <null> (iris_dri.so+0xcb6ef6) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #3 __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 (libc.so.6+0x2a1c9) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)

  Previous write of size 8 at 0x722c00005800 by thread T1:
    #0 malloc ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:665 (libtsan.so.2+0x54b3f) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 <null> <null> (iris_dri.so+0xf8f9c) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #2 <null> <null> (iris_dri.so+0xfcddf) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)

  Mutex M0 (0x723000000010) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1341 (libtsan.so.2+0x59a13) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13/bits/gthr-default.h:749 (libsfml-window-d.so.3.0+0x16d72) (BuildId: 8704cd2c91e737ba5b08bf26b6f6abf752c7c9b0)
    #2 __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 (libc.so.6+0x2a1c9) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)

  Mutex M1 (0x7ffff6dfdf50) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1341 (libtsan.so.2+0x59a13) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13/bits/gthr-default.h:749 (libsfml-window-d.so.3.0+0x16d72) (BuildId: 8704cd2c91e737ba5b08bf26b6f6abf752c7c9b0)
    #2 __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 (libc.so.6+0x2a1c9) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)

  Thread T1 'SF:disk$0' (tid=140095, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1022 (libtsan.so.2+0x5ac1a) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 <null> <null> (iris_dri.so+0x11d924) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #2 __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 (libc.so.6+0x2a1c9) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)

SUMMARY: ThreadSanitizer: data race (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xf5282) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe) 
==================
ThreadSanitizer: reported 1 warnings

@eXpl0it3r
Copy link
Member
eXpl0it3r commented Dec 11, 2024

The last part sounds like a driver bug (see also iris_dri).

Any reason you're not just using find_package for SFML as well?

@viencent2
Copy link
Author
viencent2 commented Dec 11, 2024

I don't use find_package as I compile SFML myself and for android as well from the same src folder. it is not installed in the system, I can just fetch from git and rebuild new version into build folder.

I have 2 ideas at this time.
1)
Sanitizer has a bug. (as on older ubuntu system there was no problem but also drivers were different)
Because it often report error in memory allocation even though the program is simple.

When SFML init GL context. iris driver starts some threads that mess up memory of the whole program.
so then I see data race on memory because the address is being used in one of the iris threads.
but one of the races I eliminated in loadFromImage by loading textures only from width() -1 height() - 1 of the original image.

@ChrisThrasher
Copy link
Member

I have not used ThreadSanitizer myself, but my understand is that using TSan requires compiling all dependencies with TSan as well. Have you done that?

@viencent2
8000 Copy link
Author

Hm, I compiled SFML with sanitizer flag as well and it just gives me more debug trace:

==================
WARNING: ThreadSanitizer: data race (pid=14277)
  Write of size 8 at 0x722c00005800 by main thread (mutexes: write M0, write M1):
    #0 free ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:724 (libtsan.so.2+0x57c71) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 <null> <null> (iris_dri.so+0xf5282) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #2 <null> <null> (iris_dri.so+0xcb6ef6) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #3 sf::priv::GlxContext::GlxContext(sf::priv::GlxContext*, sf::ContextSettings const&, sf::Vector2<unsigned int>) <null> (libsfml-window.so.3.0+0x37b1d) (BuildId: 1d2f6f0040590fe0c3ac9bee290bd100902bcab4)
    #4 sf::priv::GlxContext::GlxContext(sf::priv::GlxContext*) <null> (libsfml-window.so.3.0+0x37877) (BuildId: 1d2f6f0040590fe0c3ac9bee290bd100902bcab4)
    #5 sf::priv::GlContext::SharedContext::SharedContext() <null> (libsfml-window.so.3.0+0x10831) (BuildId: 1d2f6f0040590fe0c3ac9bee290bd100902bcab4)
    #6 sf::priv::GlContext::SharedContext::get() <null> (libsfml-window.so.3.0+0xf918) (BuildId: 1d2f6f0040590fe0c3ac9bee290bd100902bcab4)
    #7 sf::priv::GlContext::getSharedContext() <null> (libsfml-window.so.3.0+0xc5f9) (BuildId: 1d2f6f0040590fe0c3ac9bee290bd100902bcab4)
    #8 sf::GlResource::GlResource() <null> (libsfml-window.so.3.0+0x12df5) (BuildId: 1d2f6f0040590fe0c3ac9bee290bd100902bcab4)
    #9 sf::Window::Window() <null> (libsfml-window.so.3.0+0x16672) (BuildId: 1d2f6f0040590fe0c3ac9bee290bd100902bcab4)
    #10 sf::RenderWindow::RenderWindow(sf::VideoMode, sf::String const&, unsigned int, sf::State, sf::ContextSettings const&) <null> (libsfml-graphics.so.3.0+0x78721) (BuildId: 829d92ff3c62484e5d9c35e9818defc763fb0d9d)
    #11 main /main.cpp:18 (+0x4013b5)

  Previous write of size 8 at 0x722c00005800 by thread T1:
    #0 malloc ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:665 (libtsan.so.2+0x54b3f) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
    #1 <null> <null> (iris_dri.so+0xf8f9c) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)
    #2 <null> <null> (iris_dri.so+0xfcddf) (BuildId: 1164c48e8f4333b4c99b65095cf99839d28361fe)

This particular issue I think is due to the driver or OS or sanitizer itself. its on ubuntu24 which is still quite raw and buggy.

However check Texture.loadFromImage function if it does not read memory out of bounds on the edge cases where rect area == image.width/height

@ChrisThrasher
Copy link
Member

my understand is that using TSan requires compiling all dependencies with TSan as well. Have you done that?

This question of mine still stands. ThreadSanitizer is not as straightforward to enable as ASan or UBSan.

@ChrisThrasher
Copy link
Member

I'm closing this issue until I hear back on whether TSan was being set up properly or if this issue can be recreated with AddressSanitizer.

@eXpl0it3r eXpl0it3r closed this as not planned Won't fix, can't repro, duplicate, stale Jun 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants
0