Git Product home page Git Product logo

ntsc-crt's People

Contributors

eliasdaler avatar f33rni avatar gumball2415 avatar itotaljustice avatar l-spiro avatar lmp88959 avatar neutralinsomniac avatar scivision avatar wel97459 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  avatar  avatar  avatar  avatar  avatar

ntsc-crt's Issues

[1] heap buffer overflow at crt_modulate

Where Crashes Happen

NTSC-CRT/crt_ntsc.c

Lines 278 to 291 in e267248

pix = s->data + ((((x * s->w) / destw) + sy) * bpp);
switch (s->format) {
case CRT_PIX_FORMAT_RGB:
case CRT_PIX_FORMAT_RGBA:
rA = pix[0];
gA = pix[1];
bA = pix[2];
break;
case CRT_PIX_FORMAT_BGR:
case CRT_PIX_FORMAT_BGRA:
rA = pix[2];
gA = pix[1];
bA = pix[0];
break;

Within the crt_modulate function, pix is defined through the operation of adding s->data and (((x * s->w) / destw) + sy) * bpp). At this time, heap buffer overflow occurs at line 288 because the operation result exceeds the buffer allocated to s->data.

Root Cuase

NTSC-CRT/bmp_rw.c

Lines 35 to 42 in e267248

f = fopen(file, "rb");
if (f == NULL) {
return NULL;
}
fread(header, sizeof(unsigned char), 54, f);
width = *(int*) &header[18];
height = *(int*) &header[22];
BPP = *(int*) &header[28];

You can check that the file given as an input in the loadBMP function is opened and read into memory. Since the value is not verified by reading width, height, and BPP, there is a possibility that the value will be a small value beyond the range of unsigned int. In other words, you can allocate a buffer smaller than the size that will be used.

NTSC-CRT/crt_ntsc.c

Lines 256 to 265 in e267248

int sy;
field_offset = (s->field * s->h + desth) / desth / 2;
sy = (y * s->h) / desth;
sy += field_offset;
if (sy >= s->h) sy = s->h;
sy *= s->w;

Therefore, out input value s->w was used without verification, resulting in integer overflow and entering 0. The result of the sy operation also became 0. So later, heap buffer overflow occurs at first paragraph.

ASAN output

==181349==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000032 at pc 0x55555555d027 bp 0x7ffffff89650 sp 0x7ffffff89640
READ of size 1 at 0x602000000032 thread T0
    #0 0x55555555d026 in crt_modulate /home/user/Analysis/NTSC-CRT/crt_ntsc.c:288
    #1 0x555555558128 in main /home/user/Analysis/NTSC-CRT/crt_main.c:241
    #2 0x7ffff73cad8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #3 0x7ffff73cae3f in __libc_start_main_impl ../csu/libc-start.c:392
    #4 0x555555558614 in _start (/home/user/Analysis/build/ntsc+0x4614)
 
0x602000000032 is located 1 bytes to the right of 1-byte region [0x602000000030,0x602000000031)
allocated by thread T0 here:
    #0 0x7ffff767da37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x55555555ddc8 in loadBMPconverter /home/user/Analysis/NTSC-CRT/bmp_rw.c:79
    #2 0x55555555ddc8 in bmp_read24 /home/user/Analysis/NTSC-CRT/bmp_rw.c:152
 
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/user/Analysis/NTSC-CRT/crt_ntsc.c:288 in crt_modulate
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa fd fa fa fa[01]fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==181349==ABORTING

POC

poc.zip

  • Input that produced the above ASAN output: poc
  • Same crash with different input: example1, example2, example3

How to reproduce

ntsc -op 640 480 24 0 crash out.ppm

Option to accept/output 24bpp RGB buffer

I am looking to utilize your encoder alongside the popular Raylib game library to provide a filtering option in a game, however the color format used is fairly unusual and forces having to go through a conversion step both for input and output to meet what the library needs. This unfortunately makes it fairly unwieldy to use it with anything other than the rendering library used.

I'd ask that it'd be possible to provide or have a version of the encoder/decoder that takes a byte array of RGB colors so it is simpler to utilize in other situations.

Left and upper side of output have black borders by default

Hello again! I managed to get the library working with Raylib to great performance, however I noticed even after adjusting a lot of parameters I couldn't really have the output occupy as much on-screen as the original input did.

For reference:

image

And NTSC-CRT's output:

image

After trying to play around with some of the sync parameters in the header, I noticed it would occasionally change where the borders are, so I assume this might be something to do with them. Have a great day!

How to batch run on .BMP files?

Hi, awesome project!

How can I process multiple frames from a video?

Files are named like this:
001.bmp
002.bmp
003.bmp
...

Can video files be supported?

I just want to know if it's possible to play video? I think you need a videocodec to show video files with CRT-NTSC filters, and is it planned at all?

ntscvideo using interlaced mode, jumps randomly between frames

Steps to recreate:

  1. ./ffmpeg -i video.mp4 -r 30 -s 640x480 frames/%06d.bmp
  2. ./ntscvideo -o 200 640 480 24
  3. ./ffmpeg -y -r 30 -i output/%06d.bmp output.mp4

For some reason, it likes to randomly jump between frames in interlaced mode. It doesn't do this in progressive mode.

[Windows] Can't get the interactive app to start (Attempting to load an image results in help being displayed on the screen)

I might be an idiot, and I'm definitely an idiot for using Windows. But hear me out. I've spent time to compile this, and trying to run the executable VS produces and adding the file just results in help being spewed out the CLI. No other window opens, and the interactive app never starts.

This is what's happening:

C:\Users\TheSystemGuy\Desktop\NTSC-CRT-v.2.3.0\build\Release>ntsc_video.exe cbar.bmp
NTSC/CRT v2.3.0 by EMMIR 2018-2023
This program does not operate on video files, only sequences of
images. Please make sure you have the FFMPEG command line tools
installed and follow these instructions to convert a video
using the NTSC/CRT library:
  mkdir frames
  mkdir output
  ffmpeg -r 1 -i your_video.mov -r 1 ./frames/$frame%06d.bmp
  ./ntsc_video.exe <arguments>
  ffmpeg -r 30 -f image2 -s 640x480 -i ./output/%06d.bmp -vcodec libx264 -crf 10 -pix_fmt yuv420p out.mp4

------------------------------------------------------------
usage: ntsc_video.exe -m|o|a|p|s|h num_frames outwidth outheight noise
sample usage: ntsc_video.exe -oa 5000 640 480 0
sample usage: ntsc_video.exe - 1400 832 624 12
-- NOTE: the - after the program name is required
------------------------------------------------------------
        m : monochrome
        o : do not prompt when overwriting files
        a : mess up the bottom of the frame (useful for the VHS look)
        s : fill in gaps between scan lines
        p : progressive scan (rather than interlaced)
        h : print help

by default, the image will be full color and interlaced

If I am a bonehead, I would love to see documentation be added for idiots like me.

[2] SEGV at loadBMP (WRITE memory access)

Root Cause

NTSC-CRT/bmp_rw.c

Lines 35 to 55 in e267248

f = fopen(file, "rb");
if (f == NULL) {
return NULL;
}
fread(header, sizeof(unsigned char), 54, f);
width = *(int*) &header[18];
height = *(int*) &header[22];
BPP = *(int*) &header[28];
size = (width * height * (BPP / 8));
padding = ((4 - (width * (BPP / 8)) % 4) % 4);
data = calloc_func(size, (BPP / 8));
if (data == NULL) {
return NULL;
}
fseek(f, 54, SEEK_SET);
for (Y = height - 1; Y >= 0; Y--) {
for (X = 0; X < width; X++) {
fread(&data[(Y * width + X) * (BPP / 8)], (BPP / 8), 1, f);
}
fread(pad, padding, 1, f);
}

You can check that the file given as an input in the loadBMP function is opened and read into memory. Since the value is not verified by reading width, height, and BPP, there is a possibility that the value will be a small value beyond the range of unsigned int. In other words, you can allocate a buffer smaller than the size that will be used.

Alternatively, if the result of the size operation on line 43 exceeds the range of unsigned int, and integer overflow is likely. Later, on line 45, a heap address of size *(BPP/8) is returned via the calloc function. The integer overflow can cause problems if the size is unintentionally small enough.

This causes a problem on line 52. When a file is read into the heap through the fread function, the buffer allocated for data overflows.

ASAN output

AddressSanitizer:DEADLYSIGNAL
=================================================================
==958252==ERROR: AddressSanitizer: SEGV on unknown address 0x7ff98f791000 (pc 0x7ff91336d9ac bp 0x000000000023 sp 0x7fffe29d67c8 T0)
==958252==The signal is caused by a WRITE memory access.
    #0 0x7ff91336d9ac  (/lib/x86_64-linux-gnu/libc.so.6+0x1a09ac)
    #1 0x7ff9132584a2 in __GI__IO_file_xsgetn libio/fileops.c:1295
    #2 0x7ff91324cc28 in __GI__IO_fread libio/iofread.c:38
    #3 0x7ff913434753 in __interceptor_fread ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1045
    #4 0x5604cb259cdb in fread /usr/include/x86_64-linux-gnu/bits/stdio2.h:293
    #5 0x5604cb259cdb in loadBMP /home/user/Analysis/NTSC-CRT/bmp_rw.c:52
    #6 0x5604cb259cdb in loadBMPconverter /home/user/Analysis/NTSC-CRT/bmp_rw.c:73
    #7 0x5604cb259cdb in bmp_read24 /home/user/Analysis/NTSC-CRT/bmp_rw.c:152
    #8 0x5604cb254207 in main /home/user/Analysis/NTSC-CRT/crt_main.c:210
    #9 0x7ff9131f6d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #10 0x7ff9131f6e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #11 0x5604cb254614 in _start (/home/user/Analysis/build/ntsc+0x4614)
 
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0x1a09ac)
==958252==ABORTING

POC

poc.zip

How to reproduce

ntsc -op 640 480 24 0 crash out.ppm

Integration into emulator.

Hi LMP88959, first of all congratulations on your project, fantastic. I would like to integrate it into my emulator (https://github.com/punesemu/puNES) among the video filters. I have already seen the license and I know I could already do it, but I prefer to ask your permission, it seems more correct to me.

[3] heap buffer overflow at loadBMPconverter

Where Crashes Happen

NTSC-CRT/bmp_rw.c

Lines 63 to 94 in e267248

static void *
loadBMPconverter(char *file, int *w, int *h,
void *(*calloc_func)(size_t, size_t))
{
unsigned int *data = NULL;
unsigned int x, y, i;
unsigned char n;
unsigned char *p;
unsigned int *pix;
p = loadBMP(file, &x, &y, &n, calloc_func);
if (p == NULL) {
return NULL;
}
*w = x;
*h = y;
data = calloc_func(x * y, sizeof(unsigned int));
if (data == NULL) {
return NULL;
}
pix = data;
if ((n / 8) == 4) {
memcpy(pix, p, (x * y * sizeof(unsigned int)));
free(p);
return data;
}
for (i = 0; i < (x * y * (n / 8)); i += (n / 8)) {
*(pix++) = (p[i] << 0) | (p[i + 1] << 8) | (p[i + 2] << 16) | (255 << 24);
}
free(p);
return data;
}

In line 73, loadBMP does return a heap address and it’s size of determined by x, y, n given.
And another allocation happens in line 79 with calloc, and this is used to copy bytes from the previous chunk.
But If you see below, because of an integer overflow inside of loadBMP, the buffer to be copied could be less than expected.

Root Cause

NTSC-CRT/bmp_rw.c

Lines 35 to 48 in e267248

f = fopen(file, "rb");
if (f == NULL) {
return NULL;
}
fread(header, sizeof(unsigned char), 54, f);
width = *(int*) &header[18];
height = *(int*) &header[22];
BPP = *(int*) &header[28];
size = (width * height * (BPP / 8));
padding = ((4 - (width * (BPP / 8)) % 4) % 4);
data = calloc_func(size, (BPP / 8));
if (data == NULL) {
return NULL;
}

You can check that the file given as an input in the loadBMP function is opened and read into memory. Since the value is not verified by reading width, height, and BPP, there is a possibility that the value will be a small value beyond the range of unsigned int. In other words, you can allocate a buffer smaller than the size that will be used.

Alternatively, if the result of the size operation on line 43 exceeds the range of unsigned int, and integer overflow is likely. Later, on line 45, a heap address of size *(BPP/8) is returned via the calloc function. The integer overflow can cause problems if the size is unintentionally small enough.

ASAN output

==960226==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000011 at pc 0x7f9418b10397 bp 0x7ffdad28d950 sp 0x7ffdad28d0f8
READ of size 12884901888 at 0x602000000011 thread T0
    #0 0x7f9418b10396 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #1 0x5570dc12ff60 in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29
    #2 0x5570dc12ff60 in loadBMPconverter /home/user/Analysis/NTSC-CRT/bmp_rw.c:85
    #3 0x5570dc12ff60 in bmp_read24 /home/user/Analysis/NTSC-CRT/bmp_rw.c:152
    #4 0x5570dc12a207 in main /home/user/Analysis/NTSC-CRT/crt_main.c:210
    #5 0x7f94188d7d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #6 0x7f94188d7e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #7 0x5570dc12a614 in _start (/home/user/Analysis/build/ntsc+0x4614)
 
0x602000000011 is located 0 bytes to the right of 1-byte region [0x602000000010,0x602000000011)
allocated by thread T0 here:
    #0 0x7f9418b8aa37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x5570dc12fc3b in loadBMP /home/user/Analysis/NTSC-CRT/bmp_rw.c:45
    #2 0x5570dc12fc3b in loadBMPconverter /home/user/Analysis/NTSC-CRT/bmp_rw.c:73
    #3 0x5570dc12fc3b in bmp_read24 /home/user/Analysis/NTSC-CRT/bmp_rw.c:152
 
SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[01]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==960226==ABORTING

POC

poc.zip
Input that produced the above ASAN output: poc
Same crash with different input: example

How to reproduce

ntsc -op 640 480 24 0 crash out.ppm

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.