Tencent / libpag

The official rendering library for PAG (Portable Animated Graphics) files that renders After Effects animations natively across multiple platforms.
https://pag.art
Other
4.73k stars 437 forks source link

segmentation fault libpag 4.1.8 #2230

Closed HBLocker closed 1 month ago

HBLocker commented 1 month ago

Which Version of libpag are you using?

Compile and load the libary to load the images. with the objective c file

#import <Foundation/Foundation.h>
#include <dlfcn.h>
#include <objc/objc.h>
#include <objc/runtime.h>

// Define a function to load the image using the dynamic library
void load(NSString *path) {
    void *handle;
    char *error;

    // Open the dynamic library
    handle = dlopen("libpag", RTLD_LAZY);
    if (!handle) {
        NSLog(@"Error opening shared library: %s", dlerror());
        return;
    }

    // Get the class object for PAGFile
    Class PAGFileClass = objc_getClass("PAGFile");

    if (!PAGFileClass) {
        NSLog(@"Failed to get class PAGFile");
        dlclose(handle);
        return;
    }

    // Get the method signature for the Load: method
    SEL loadSelector = NSSelectorFromString(@"Load:");
    Method loadMethod = class_getClassMethod(PAGFileClass, loadSelector);
    if (!loadMethod) {
        NSLog(@"Failed to get method Load:");
        dlclose(handle);
        return;
    }

    // Get the function pointer for the Load: method
    IMP loadFunction = method_getImplementation(loadMethod);

    ((void (*)(id, SEL, NSString *))loadFunction)(PAGFileClass, loadSelector, path);

    // Close the dynamic library
    dlclose(handle);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        if (argc != 2) {
            NSLog(@"Usage: %s <image_path>", argv[0]);
            return 1;
        }

        // Convert C string to NSString
        NSString *path = [NSString stringWithUTF8String:argv[1]];

        // Call the fuzz function to load the image using the dynamic library
        load(path);
    }
    return 0;
}
%  ./load nighty/crashes/access_violation_0xxxxxxxa80_0xxxxxxxbed_1 
Get webP size fail.
AddressSanitizer:DEADLYSIGNAL
=================================================================
==6301==ERROR: AddressSanitizer: SEGV on unknown address 0x000126d13bed (pc 0x000107179a80 bp 0x00016d3d6b30 sp 0x00016d3d6b20 T0)
==6301==The signal is caused by a READ memory access.
    #0 0x107179a80 in tgfx::DataView::readData(unsigned long, unsigned char*, unsigned long) const+0x7c (libpag:arm64+0x139a80)
    #1 0x107179b68 in tgfx::DataView::getUint16(unsigned long) const+0x18 (libpag:arm64+0x139b68)
    #2 0x1070a0dfc in pag::DecodeStream::readUint16()+0x2c (libpag:arm64+0x60dfc)
    #3 0x107066a18 in pag::ReadTagHeader(pag::DecodeStream*)+0x10 (libpag:arm64+0x26a18)
    #4 0x107091860 in void pag::ReadTags<pag::VectorComposition*>(pag::DecodeStream*, pag::VectorComposition*, void (*)(pag::DecodeStream*, pag::TagCode, pag::VectorComposition*))+0x84 (libpag:arm64+0x51860)
    #5 0x1070917a8 in pag::ReadVectorComposition(pag::DecodeStream*)+0x7c (libpag:arm64+0x517a8)
    #6 0x107076c20 in pag::ReadTag_VectorCompositionBlock(pag::DecodeStream*, pag::CodecContext*)+0x14 (libpag:arm64+0x36c20)
    #7 0x107076f24 in std::__1::function<void (pag::DecodeStream*, pag::CodecContext*)>::operator()(pag::DecodeStream*, pag::CodecContext*) const+0x28 (libpag:arm64+0x36f24)
    #8 0x107076ee8 in pag::ReadTagsOfFile(pag::DecodeStream*, pag::TagCode, pag::CodecContext*)+0x3c (libpag:arm64+0x36ee8)
    #9 0x107053f10 in pag::Codec::Decode(void const*, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x11c (libpag:arm64+0x13f10)
    #10 0x1070442ac in pag::File::Load(void const*, unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x16c (libpag:arm64+0x42ac)
    #11 0x1070440f0 in pag::File::Load(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x34 (libpag:arm64+0x40f0)
    #12 0x1070f7de8 in pag::PAGFile::Load(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x18 (libpag:arm64+0xb7de8)
    #13 0x1070a8164 in +[PAGFileImpl Load:]+0xfc (libpag:arm64+0x68164)
    #14 0x102a2b9fc in fuzz load.m:40
    #15 0x102a2bae8 in main load.m:57
    #16 0x182d190dc  (<unknown module>)

==6301==Register values:
 x[0] = 0x000000016d3d6f00   x[1] = 0x000000001f00ff42   x[2] = 0x000000016d3d6b48   x[3] = 0x0000000000000002  
 x[4] = 0x0000000106500fc0   x[5] = 0x0000000000000001   x[6] = 0x000000016cbdc000   x[7] = 0x0000000000000001  
 x[8] = 0x0000000000000002   x[9] = 0x0000000107d03cab  x[10] = 0x000000000000003f  x[11] = 0x000000000000000e  
x[12] = 0x0000000000000061  x[13] = 0x0000000000184000  x[14] = 0x0000000000007e01  x[15] = 0x0000000000000006  
x[16] = 0x00000001032e4a98  x[17] = 0x00000001033240b8  x[18] = 0x0000000000000000  x[19] = 0x0000000000000002  
x[20] = 0x00000000e0ff00bd  x[21] = 0x000000016d3d6ef8  x[22] = 0x1f00ff03000003c0  x[23] = 0x000000016d3d6d70  
x[24] = 0x000000016d3d7240  x[25] = 0x0000000182d9862b  x[26] = 0x0000000000000000  x[27] = 0x0000000000000000  
x[28] = 0x0000000000000000     fp = 0x000000016d3d6b30     lr = 0x0000000107179b6c     sp = 0x000000016d3d6b20  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (libpag:arm64+0x139a80) in tgfx::DataView::readData(unsigned long, unsigned char*, unsigned long) const+0x7c
==6301==ABORTING
zsh: abort      ./load nighty/crashes/access_violation_0xxxxxxxa80_0xxxxxxxbed_1

seg_crashes.zip

kevingpqi123 commented 1 month ago

这样做的原因是啥?pag 提供了 OC 的接口,如果需要 C++ 编程,同样可以使用 C++ 的头文件,这么麻烦处理的原因是啥? 建议系统了解下 pag 的官方文档和 API 接口

HBLocker commented 1 month ago

我想直接加载库,但我在调用时遇到问题,所以我可以调用 dylib 将其加载到内存中进行模糊测试。

对我来说,直接从 dylib 将其加载到 meory 中也更容易,我正在对微信进行研究,想看看我是否会在 libary 中遇到 poc 崩溃。 当我安装它时,我在 VS Code 中遇到了头文件的错误和链接器问题,因此我只是加载它并调用库中的函数来加载图像。 (谷歌翻译)

kevingpqi123 commented 1 month ago

If you are on a macOS or iOS platform, you can directly load the XCFramework for PAG based on pods. Why make it so complicated? Please describe the functionality you want to implement and provide a clear background. We will then be able to recommend a suitable solution.

HBLocker commented 1 month ago

我只是想将图像加载到库中对其进行模糊测试,因此我加载了库并以这种方式调用它,这与模糊器内存初始化及其工作原理有关: https://github.com/googleprojectzero/Jackalope

kevingpqi123 commented 1 month ago

If you want to use PAG with C++ code, the test cases in PAG are based on C++. You can refer to the CMake files in the main directory and the test cases in the source code for guidance.

HBLocker commented 1 month ago

yes, I understand the the issue is still in the code. The code I have provided uses the same interface as reffrenced in the api to load the files, I just call the dylib directly and load a image each time. When I loaded the image, I was using the documentation to do so.

 % ./load nighty/crashes/access_violation_0xxxxxxxa80_0xxxxxxx4db_1
AddressSanitizer:DEADLYSIGNAL
=================================================================
==6591==ERROR: AddressSanitizer: SEGV on unknown address 0x000125f114db (pc 0x000107279a80 bp 0x00016d246b30 sp 0x00016d246b20 T0)
==6591==The signal is caused by a READ memory access.
    #0 0x107279a80 in tgfx::DataView::readData(unsigned long, unsigned char*, unsigned long) const+0x7c (libpag:arm64+0x139a80)
    #1 0x107279b68 in tgfx::DataView::getUint16(unsigned long) const+0x18 (libpag:arm64+0x139b68)
    #2 0x1071a0dfc in pag::DecodeStream::readUint16()+0x2c (libpag:arm64+0x60dfc)
    #3 0x107166a18 in pag::ReadTagHeader(pag::DecodeStream*)+0x10 (libpag:arm64+0x26a18)
    #4 0x107191860 in void pag::ReadTags<pag::VectorComposition*>(pag::DecodeStream*, pag::VectorComposition*, void (*)(pag::DecodeStream*, pag::TagCode, pag::VectorComposition*))+0x84 (libpag:arm64+0x51860)
    #5 0x1071917a8 in pag::ReadVectorComposition(pag::DecodeStream*)+0x7c (libpag:arm64+0x517a8)
    #6 0x107176c20 in pag::ReadTag_VectorCompositionBlock(pag::DecodeStream*, pag::CodecContext*)+0x14 (libpag:arm64+0x36c20)
    #7 0x107176f24 in std::__1::function<void (pag::DecodeStream*, pag::CodecContext*)>::operator()(pag::DecodeStream*, pag::CodecContext*) const+0x28 (libpag:arm64+0x36f24)
    #8 0x107176ee8 in pag::ReadTagsOfFile(pag::DecodeStream*, pag::TagCode, pag::CodecContext*)+0x3c (libpag:arm64+0x36ee8)
    #9 0x107153f10 in pag::Codec::Decode(void const*, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x11c (libpag:arm64+0x13f10)
    #10 0x1071442ac in pag::File::Load(void const*, unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x16c (libpag:arm64+0x42ac)
    #11 0x1071440f0 in pag::File::Load(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x34 (libpag:arm64+0x40f0)
    #12 0x1071f7de8 in pag::PAGFile::Load(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&)+0x18 (libpag:arm64+0xb7de8)
    #13 0x1071a8164 in +[PAGFileImpl Load:]+0xfc (libpag:arm64+0x68164)
    #14 0x102bbb9fc in fuzz load.m:40
    #15 0x102bbbae8 in main load.m:57
    #16 0x182d190dc  (<unknown module>)

==6591==Register values:
 x[0] = 0x000000016d246f00   x[1] = 0x000000001f00ff8c   x[2] = 0x000000016d246b48   x[3] = 0x0000000000000002  
 x[4] = 0x0000000106600fc0   x[5] = 0x0000000000000001   x[6] = 0x000000016ca4c000   x[7] = 0x0000000000000001  
 x[8] = 0x0000000000000002   x[9] = 0x0000000106f0154f  x[10] = 0x0000000000000089  x[11] = 0x0000000000000000  
x[12] = 0x0000000000000000  x[13] = 0x0000000000000000  x[14] = 0x0000000000007e01  x[15] = 0x0000000000000006  
x[16] = 0x0000000103474a98  x[17] = 0x00000001034b40b8  x[18] = 0x0000000000000000  x[19] = 0x0000000000000002  
x[20] = 0x00000000e0ff0073  x[21] = 0x000000016d246ef8  x[22] = 0x1f00ff03000003c0  x[23] = 0x000000016d246d70  
x[24] = 0x000000016d247240  x[25] = 0x0000000182d9862b  x[26] = 0x0000000000000000  x[27] = 0x0000000000000000  
x[28] = 0x0000000000000000     fp = 0x000000016d246b30     lr = 0x0000000107279b6c     sp = 0x000000016d246b20  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (libpag:arm64+0x139a80) in tgfx::DataView::readData(unsigned long, unsigned char*, unsigned long) const+0x7c
==6591==ABORTING
zsh: abort      ./load nighty/crashes/access_violation_0xxxxxxxa80_0xxxxxxx4db_1
kevingpqi123 commented 1 month ago

I have reviewed the attachments in this post (https://github.com/Tencent/libpag/issues/2229), and it seems that the PAG files provided there are invalid. They cannot be opened using the desktop preview tool. May I know the source of these PAG files?

HBLocker commented 1 month ago

They are mutated by the fuzzer so they will be scrambled.

kevingpqi123 commented 1 month ago

The generation of PAG files is based on our provided After Effects export plugin or conversion tool. If your PAG files are generated through other channels, there may be decoding issues.

HBLocker commented 1 month ago

Yes, the idea was to find bugs in libpag, so the images will be scrambled to find issues within the library

domchen commented 1 month ago

As replied in #2229, we are working on fixing the memory issue related to the strlen() method. However, I am having some difficulty identifying the root cause of the issue described above. Would it be possible for you to upload a runnable project? This would greatly expedite the process. Thank you.

domchen commented 1 month ago

I've identified the root cause of this problem: a uint32_t overflow occurred in DecodeStream::checkEndOfFile(), leading to the failure of the boundary check.

domchen commented 1 month ago

Fixed in #2243

HBLocker commented 1 month ago

Thank you! May I request a cve for these issues?

domchen commented 1 month ago

Certainly, please proceed, and feel free to inform me if any confirmation or action is required from my end.