Giter VIP home page Giter VIP logo

xiaozhuai / imageinfo Goto Github PK

View Code? Open in Web Editor NEW
104.0 104.0 26.0 14.9 MB

Free Palestine🇵🇸🇵🇸🇵🇸Cross platform super fast single header c++ library to get image size and format without loading/decoding. Support avif, bmp, cur, dds, gif, hdr (pic), heic (heif), icns, ico, j2k, jp2, jpeg (jpg), jpx, ktx, png, psd, qoi, tga, tiff (tif), webp ...

License: MIT License

CMake 4.60% C++ 95.40%

imageinfo's Introduction

xiaozhuai

imageinfo's People

Contributors

chan233 avatar mis1eader-dev avatar omrdk avatar xiaozhuai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

imageinfo's Issues

JPEG contains garbge bytes

Yakari T01-0000
in this jpeg file, there's a section with comment text (FF FE) of size 3 bytes, unfortunately, it seems that the minimum size of a section is 4 bytes, so the next iteration moves the cursor to the wrong place.

Add another format stage

Currently if the likely_formats is not met, it goes on to search all other formats. Which may not be needed by the application.

We can make it into 3 stages:

  1. likely_formats: Checks those first, which is a hint given by the programmer that this file is very likely to be in that format. Say the user gave a .png file, then the library can start parsing using the png parser.
  2. supported_formats: If likely_formats failed, it starts looking into the supported formats only, instead of looking into the entire map.
  3. Every other format: If all else fails and the boolean argument must_be_one_of_likely_formats is false, then it starts checking against all other formats.

It is also possible to do it in another way, which is we add a single optional format at the top stage, called very_likely_format, which is hinted to the library by the programmer that this format must be checked first, as it is very likely true. Then it can go in likely_formats to look if it wasn't that format.

关于读取图像信息和元数据信息的需求

捕获

图像常用信息包括:格式、宽高、DPI及单位、色彩深度/色彩位数/通道位数(1、2、4、8、16),色彩通道(1、3、4,还有索引通道或者其它什么),色彩空间(黑白、索引、sRGB、cmyk等等),压缩方式及质量(仅部分格式)

元数据除了图像自带的Tag,还包括Exif,IPTC,XMP,JFIF / JFXX,ICC Profiles,Photoshop。
Exif信息是识别图像必须要读取的。Exit常用信息包括:宽、高、DPI及单位、色彩通道、通道位数、每像素通道数、色彩空间、原始日期、方向、GPS等等若干。

个人实践:图像格式、宽高像素、宽高DPI及单位、位数、通道数、色彩空间、压缩方式及质量、图像旋转方向、原始日期。这些11项是经常用到的,如果图像数据提供的话必须要能识别。

我现在用ImageMagick和metadata-extractor-dotnet来识别,前者优点是格式全,缺点是要读取全部图像数据,速度太慢。后者能识别各种格式的元数据,但是输出太全面了,外行也看不明白,没啥必要。

ImageInfo比较符合日常需求,识别的图像格式也足够。如果能识别图像格式的主要元数据就非常完美了。

当然,这是个慢功夫的活。

RawDataReader 错误

class RawDataReader {
public:
    explicit RawDataReader(RawData data) : data_(data) {}

    inline size_t size() const { return data_.length; }

    inline void read(void *buf, off_t offset, size_t size) const { memcpy(buf, ((char *)data_.data) + offset, size); }

private:
    RawData data_;
}; 

当我批量判断 时,read 函数 出现错误

0x00007FFA714FFD36 (vcruntime140d.dll)处(位于 Compress_test.exe 中)引发的异常: 0xC0000005: 读取位置 0x000001F6BA5397EE 时发生访问冲突。

我的调用如下
unsigned char* ALLImgData;
ALLImgData = new unsigned char[totalSize];
auto info = imageinfo::parseimageinfo::RawDataReader(imageinfo::RawData(ALLImgData, bufferSize));

Security Issue Report

Project address

afl_imageinfo

asan_imageinfo

poc:id02

Build original project

cmake -B build .
cmake --build build -- all
cmake --build build -- check

Build afl project

Cmakelist.txt add:

set (CMAKE_C_COMPILER "/usr/local/bin/afl-clang-fast")
set (CMAKE_CXX_COMPILER "/usr/local/bin/afl-clang-fast++")

Run

./imageinfo id02

02

Vulnerability type

READ memory access causes SEGV stack overflow.

ASAN

ubuntu@ubuntu:~/Desktop/imageinfo/imageinfo/build$ ./imageinfo ../../build/output/default/crashes/id\:000002\,sig\:11\,src\:000007\,time\:76911\,execs\:21200\,op\:havoc\,rep\:16 
AddressSanitizer:DEADLYSIGNAL
=================================================================
==3079903==ERROR: AddressSanitizer: SEGV on unknown address 0x6110010000bc (pc 0x555555583ae4 bp 0x7fffffffd7e0 sp 0x7fffffffd230 T0)
==3079903==The signal is caused by a READ memory access.
    #0 0x555555583ae3 in {lambda(unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)#1}::operator()(unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&) const (/home/ubuntu/Desktop/imageinfo/imageinfo/build/imageinfo+0x2fae3)
    #1 0x5555555843c1 in _ZNSt17_Function_handlerIFbmR15IIReadInterfaceRlS2_RSt6vectorISt5arrayIlLm2EESaIS5_EEEUlmS1_S2_S2_S8_E_E9_M_invokeERKSt9_Any_dataOmS1_S2_S2_S8_ (/home/ubuntu/Desktop/imageinfo/imageinfo/build/imageinfo+0x303c1)
    #2 0x55555557cf11 in main (/home/ubuntu/Desktop/imageinfo/imageinfo/build/imageinfo+0x28f11)
    #3 0x7ffff7068082 in __libc_start_main ../csu/libc-start.c:308
    #4 0x55555556adad in _start (/home/ubuntu/Desktop/imageinfo/imageinfo/build/imageinfo+0x16dad)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/ubuntu/Desktop/imageinfo/imageinfo/build/imageinfo+0x2fae3) in {lambda(unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)#1}::operator()(unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&) const
==3079903==ABORTING

GDB

ubuntu@ubuntu:~/Desktop/imageinfo/build$ gdb --args ./imageinfo output/default/crashes/id\:000002\,sig\:11\,src\:000007\,time\:76911\,execs\:21200\,op\:havoc\,rep\:16 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./imageinfo...

gdb-peda$ r output/default/crashes/id\:000002\,sig\:11\,src\:000007\,time\:76911\,execs\:21200\,op\:havoc\,rep\:16 
Starting program: /home/ubuntu/Desktop/imageinfo/build/imageinfo output/default/crashes/id\:000002\,sig\:11\,src\:000007\,time\:76911\,execs\:21200\,op\:havoc\,rep\:16

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x65cb60 --> 0x726c646821000000 ('')
RBX: 0x6 
RCX: 0x100007c 
RDX: 0x87 
RSI: 0x4477a0 --> 0x0 
RDI: 0x4477a0 --> 0x0 
RBP: 0xf3000000 
RSP: 0x7fffffffda10 --> 0x7fffffffda58 --> 0x65cb60 --> 0x726c646821000000 ('')
RIP: 0x4113d1 (<std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2561>:	mov    esi,DWORD PTR [rax+rcx*1])
R8 : 0x1 
R9 : 0x7fffffffda40 --> 0xf3 
R10: 0x40456b --> 0x5f007465736d656d ('memset')
R11: 0x7ffff7c61be0 --> 0x65cc50 --> 0x1a3809 
R12: 0x7fffffffdbd0 --> 0xffffffffffffffff 
R13: 0xf0ffffe6 
R14: 0x7fffffffdbd8 --> 0xffffffffffffffff 
R15: 0x4457b0 --> 0x4477a0 --> 0x0
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x4113c8 <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2552>:	add    bl,0x1
   0x4113cb <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2555>:	adc    bl,0x0
   0x4113ce <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2558>:	mov    BYTE PTR [rsi+rdx*1],bl
=> 0x4113d1 <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2561>:	mov    esi,DWORD PTR [rax+rcx*1]
   0x4113d4 <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2564>:	bswap  esi
   0x4113d6 <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2566>:	cmp    DWORD PTR [rax+rcx*1+0x4],0x70727069
   0x4113de <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2574>:	
    jne    0x411358 <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2440>:	    jne    0x411358 <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2440>
   0x4113e4 <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2580>:	
    jmp    0x41138d <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2493>:	    jmp    0x41138d <std::_Function_handler<bool (unsigned long, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&), $_0>::_M_invoke(std::_Any_data const&, unsigned long&&, IIReadInterface&, long&, long&, std::vector<std::array<long, 2ul>, std::allocator<std::array<long, 2ul> > >&)+2493>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffda10 --> 0x7fffffffda58 --> 0x65cb60 --> 0x726c646821000000 ('')
0008| 0x7fffffffda18 --> 0x8 
0016| 0x7fffffffda20 --> 0x4 
0024| 0x7fffffffda28 --> 0x0 
0032| 0x7fffffffda30 --> 0x0 
0040| 0x7fffffffda38 --> 0x0 
0048| 0x7fffffffda40 --> 0xf3 
0056| 0x7fffffffda48 --> 0x7ffff7b052f6 (<_IO_new_file_fopen+534>:	mov    rbx,rax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
$_0::operator() (this=<optimized out>, length=0x417, ri=..., width=<optimized out>, height=<optimized out>, entrySizes=...) at /home/ubuntu/Desktop/imageinfo/imageinfo.hpp:498
498	                        uint32_t boxSize = buffer.readU32BE(offset);

Original code

                    off_t offset = 0; // typedef long _off_t; off_t offset = 0;
                    off_t end = metaLength;

                    while (offset < end) {
                        uint32_t boxSize = buffer.readU32BE(offset); // uint32_t readU32BE;
                        if (buffer.cmpAnyOf(offset + 4, 4, {"iprp", "ipco"})) {
                            end = offset + boxSize;
                            offset += 8;
                        } else if (buffer.cmp(offset + 4, 4, "ispe")) {
                            width = buffer.readU32BE(offset + 12);
                            height = buffer.readU32BE(offset + 16);
                            return true;
                        } else {
                            offset += boxSize;
                        }
                    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.