mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 19:06:15 +08:00
UPDATE: Harden bink2 bridge (#385)
fix stride overflow, check decode return values, null movie on open failure
This commit is contained in:
@@ -5,47 +5,62 @@
|
|||||||
* Build this small adapter with a licensed RAD Bink 2 SDK. The SDK and its
|
* Build this small adapter with a licensed RAD Bink 2 SDK. The SDK and its
|
||||||
* headers are not distributed by SharpEmu. See docs/bink2-bridge.md.
|
* headers are not distributed by SharpEmu. See docs/bink2-bridge.md.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "bink.h"
|
#include "bink.h"
|
||||||
|
|
||||||
typedef struct sharpemu_bink2_info {
|
typedef struct sharpemu_bink2_info {
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t frames_per_second_numerator;
|
uint32_t frames_per_second_numerator;
|
||||||
uint32_t frames_per_second_denominator;
|
uint32_t frames_per_second_denominator;
|
||||||
} sharpemu_bink2_info;
|
} sharpemu_bink2_info;
|
||||||
|
|
||||||
int sharpemu_bink2_open_utf8(const char *path, HBINK *movie, sharpemu_bink2_info *info) {
|
int sharpemu_bink2_open_utf8(const char *path, HBINK *movie, sharpemu_bink2_info *info) {
|
||||||
HBINK bink;
|
HBINK bink;
|
||||||
if (!path || !movie || !info) return 0;
|
if (!path || !movie || !info) return 0;
|
||||||
|
|
||||||
bink = BinkOpen(path, 0);
|
*movie = NULL;
|
||||||
if (!bink) return 0;
|
|
||||||
|
|
||||||
*movie = bink;
|
bink = BinkOpen(path, 0);
|
||||||
info->width = bink->Width;
|
if (!bink) return 0;
|
||||||
info->height = bink->Height;
|
|
||||||
info->frames_per_second_numerator = bink->FrameRate;
|
if (bink->Width == 0 || bink->Height == 0) {
|
||||||
info->frames_per_second_denominator = bink->FrameRateDiv;
|
BinkClose(bink);
|
||||||
return 1;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*movie = bink;
|
||||||
|
info->width = bink->Width;
|
||||||
|
info->height = bink->Height;
|
||||||
|
info->frames_per_second_numerator = bink->FrameRate;
|
||||||
|
info->frames_per_second_denominator = bink->FrameRateDiv;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sharpemu_bink2_decode_next_bgra(HBINK movie, uint8_t *destination,
|
int sharpemu_bink2_decode_next_bgra(HBINK movie, uint8_t *destination,
|
||||||
uint32_t stride, uint32_t destination_bytes) {
|
uint32_t stride, uint32_t destination_bytes) {
|
||||||
uint64_t needed;
|
uint64_t needed;
|
||||||
if (!movie || !destination || stride < movie->Width * 4) return 0;
|
uint64_t min_stride;
|
||||||
needed = (uint64_t)stride * movie->Height;
|
|
||||||
if (needed > destination_bytes) return 0;
|
|
||||||
|
|
||||||
/* Async Bink I/O has not filled the next frame yet; retry on the next host present. */
|
if (!movie || !destination) return 0;
|
||||||
if (BinkWait(movie)) return 0;
|
|
||||||
BinkDoFrame(movie);
|
min_stride = (uint64_t)movie->Width * 4;
|
||||||
BinkCopyToBuffer(movie, destination, stride, movie->Height, 0, 0, BINKSURFACE32RA);
|
if ((uint64_t)stride < min_stride) return 0;
|
||||||
BinkNextFrame(movie);
|
|
||||||
return 1;
|
needed = (uint64_t)stride * movie->Height;
|
||||||
|
if (needed > destination_bytes) return 0;
|
||||||
|
|
||||||
|
/* Async Bink I/O has not filled the next frame yet; retry on the next host present. */
|
||||||
|
if (BinkWait(movie)) return 0;
|
||||||
|
|
||||||
|
if (!BinkDoFrame(movie)) return 0;
|
||||||
|
|
||||||
|
if (!BinkCopyToBuffer(movie, destination, stride, movie->Height, 0, 0, BINKSURFACE32RA)) return 0;
|
||||||
|
|
||||||
|
BinkNextFrame(movie);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sharpemu_bink2_close(HBINK movie) {
|
void sharpemu_bink2_close(HBINK movie) {
|
||||||
if (movie) BinkClose(movie);
|
if (movie) BinkClose(movie);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user