From d89e70d396dc20d1693f7bbc0a5e9278182b12a5 Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Tue, 16 Jun 2026 01:48:22 -0400 Subject: [PATCH 1/5] Fix unsound pointer-to-long casts that truncate on LLP64 Casting AVFilterContext* to C long truncated the high 32 bits on LLP64 platforms (64-bit Windows), so distinct contexts could collide on the same _context_by_ptr key. Key on size_t instead, which is pointer-width everywhere. Also route object addresses through uintptr_t rather than signed long long in OpaqueContainer.add. --- av/filter/graph.pxd | 2 +- av/filter/graph.py | 4 ++-- av/filter/link.py | 4 ++-- av/opaque.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/av/filter/graph.pxd b/av/filter/graph.pxd index 11e3644c6..f67053016 100644 --- a/av/filter/graph.pxd +++ b/av/filter/graph.pxd @@ -18,7 +18,7 @@ cdef class Graph: cdef _register_context(self, FilterContext) cdef _auto_register(self) cdef int _nb_filters_seen - cdef dict[long, FilterContext] _context_by_ptr + cdef dict[size_t, FilterContext] _context_by_ptr cdef dict[str, list[FilterContext]] _context_by_type cdef list[FilterContext] _video_sources cdef list[FilterContext] _audio_sources diff --git a/av/filter/graph.py b/av/filter/graph.py index e7ce7bc9b..7463c5a5c 100644 --- a/av/filter/graph.py +++ b/av/filter/graph.py @@ -111,7 +111,7 @@ def add(self, filter, args=None, **kwargs): @cython.cfunc def _register_context(self, ctx: FilterContext): name: str = ctx.filter.ptr.name - self._context_by_ptr[cython.cast(cython.long, ctx.ptr)] = ctx + self._context_by_ptr[cython.cast(cython.size_t, ctx.ptr)] = ctx self._context_by_type.setdefault(name, []).append(ctx) if name == "buffer": self._video_sources.append(ctx) @@ -128,7 +128,7 @@ def _auto_register(self): # point we don't expose that in the API, so we should be okay... for i in range(self._nb_filters_seen, self.ptr.nb_filters): c_ctx = self.ptr.filters[i] - if cython.cast(cython.long, c_ctx) in self._context_by_ptr: + if cython.cast(cython.size_t, c_ctx) in self._context_by_ptr: continue filter_ = wrap_filter(c_ctx.filter) py_ctx = wrap_filter_context(self, filter_, c_ctx) diff --git a/av/filter/link.py b/av/filter/link.py index 0e5b680ce..2b687e194 100644 --- a/av/filter/link.py +++ b/av/filter/link.py @@ -33,7 +33,7 @@ def input(self): else: # nobreak raise RuntimeError("could not find link in context") graph: Graph = self.graph - ctx = graph._context_by_ptr[cython.cast(cython.long, cctx)] + ctx = graph._context_by_ptr[cython.cast(cython.size_t, cctx)] self._input = ctx.outputs[i] return self._input @@ -50,7 +50,7 @@ def output(self): raise RuntimeError("could not find link in context") try: graph: Graph = self.graph - ctx = graph._context_by_ptr[cython.cast(cython.long, cctx)] + ctx = graph._context_by_ptr[cython.cast(cython.size_t, cctx)] except KeyError: raise RuntimeError( "could not find context in graph", (cctx.name, cctx.filter.name) diff --git a/av/opaque.py b/av/opaque.py index d6696289b..e55468c44 100644 --- a/av/opaque.py +++ b/av/opaque.py @@ -27,7 +27,7 @@ def __cinit__(self): @cython.cfunc def add(self, v: object) -> cython.pointer[lib.AVBufferRef]: # Use object's memory address as key - key: uintptr_t = cython.cast(cython.longlong, id(v)) + key: uintptr_t = cython.cast(uintptr_t, id(v)) self._objects[key] = v data: u8ptr = cython.cast(u8ptr, lib.av_malloc(sizeof(uintptr_t))) From 352f416242ed64284f0e008f2181aef9c15d4539 Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Tue, 16 Jun 2026 01:54:42 -0400 Subject: [PATCH 2/5] Silence MSVC C4267 size_t->int narrowing in Packet.__init__ av_new_packet() and AVPacket.size take int, but size stays size_t for av_buffer_create(). FFmpeg caps packet sizes at int range, so make the narrowing explicit to suppress the warning on Windows. --- av/packet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/av/packet.py b/av/packet.py index 7886b37ad..8be300661 100644 --- a/av/packet.py +++ b/av/packet.py @@ -237,7 +237,7 @@ def __init__(self, input=None): if isinstance(input, int): size = input if size: - err_check(lib.av_new_packet(self.ptr, size)) + err_check(lib.av_new_packet(self.ptr, cython.cast(cython.int, size))) else: source = bytesource(input) size = source.length @@ -256,7 +256,7 @@ def __init__(self, input=None): raise MemoryError("Could not allocate AVBufferRef") self.ptr.buf = buf self.ptr.data = source.ptr - self.ptr.size = size + self.ptr.size = cython.cast(cython.int, size) def __repr__(self): stream = self._stream.index if self._stream else 0 From 40295064becf84f6c4e8ce84596f43777678b90a Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Tue, 16 Jun 2026 02:02:07 -0400 Subject: [PATCH 3/5] Fix MSVC narrowing warnings in audio/codec/container - AudioFrame._init: explicit int cast on _buffer_size -> avcodec_fill_audio_frame (C4267) - CodecContext: explicit int casts on extradata_size and parser in_size (C4267) - avcodec.pxd: bit_rate, rc_max_rate, rc_min_rate are int64_t in FFmpeg, not int; widen bit_rate setter to match (C4244, also fixes >2^31 truncation) - avformat.pxd: AVChapter.id is int64_t, not int (C4244, fixes id truncation) - Container.set_chapters: explicit uint cast on nb_chapters = count (C4244) --- av/audio/frame.py | 2 +- av/codec/context.py | 8 +++++--- av/container/core.py | 2 +- include/avcodec.pxd | 6 +++--- include/avformat.pxd | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/av/audio/frame.py b/av/audio/frame.py index c843c9efd..214a947e3 100644 --- a/av/audio/frame.py +++ b/av/audio/frame.py @@ -78,7 +78,7 @@ def _init( self.layout.nb_channels, cython.cast(lib.AVSampleFormat, self.ptr.format), self._buffer, - self._buffer_size, + cython.cast(cython.int, self._buffer_size), align, ) ) diff --git a/av/codec/context.py b/av/codec/context.py index 9b51c1430..6e10aaf9b 100644 --- a/av/codec/context.py +++ b/av/codec/context.py @@ -207,7 +207,7 @@ def extradata(self, data): if not self.ptr.extradata: raise MemoryError("Cannot allocate extradata") memcpy(self.ptr.extradata, source.ptr, source.length) - self.ptr.extradata_size = source.length + self.ptr.extradata_size = cython.cast(cython.int, source.length) @property def extradata_size(self): @@ -294,7 +294,9 @@ def parse(self, raw_input=None): source: ByteSource = bytesource(raw_input, allow_none=True) in_data: cython.p_uchar = source.ptr if source is not None else cython.NULL - in_size: cython.int = source.length if source is not None else 0 + in_size: cython.int = ( + cython.cast(cython.int, source.length) if source is not None else 0 + ) out_data: cython.p_uchar out_size: cython.int @@ -642,7 +644,7 @@ def bit_rate(self): return self.ptr.bit_rate if self.ptr.bit_rate > 0 else None @bit_rate.setter - def bit_rate(self, value: cython.int): + def bit_rate(self, value: cython.longlong): self.ptr.bit_rate = value @property diff --git a/av/container/core.py b/av/container/core.py index c6cdfe7fe..bd82e86a4 100755 --- a/av/container/core.py +++ b/av/container/core.py @@ -487,7 +487,7 @@ def set_chapters(self, chapters): ) ch_array[i] = ch - self.ptr.nb_chapters = count + self.ptr.nb_chapters = cython.cast(cython.uint, count) self.ptr.chapters = ch_array diff --git a/include/avcodec.pxd b/include/avcodec.pxd index 534f1ae1b..4e43b5bf1 100644 --- a/include/avcodec.pxd +++ b/include/avcodec.pxd @@ -232,7 +232,7 @@ cdef extern from "libavcodec/avcodec.h" nogil: void* opaque - int bit_rate + int64_t bit_rate int flags int flags2 uint8_t *extradata @@ -269,8 +269,8 @@ cdef extern from "libavcodec/avcodec.h" nogil: int qmin int qmax int rc_buffer_size - int rc_max_rate - int rc_min_rate + int64_t rc_max_rate + int64_t rc_min_rate AVHWAccel *hwaccel AVBufferRef *hw_device_ctx diff --git a/include/avformat.pxd b/include/avformat.pxd index 1cd07d814..06262c41a 100644 --- a/include/avformat.pxd +++ b/include/avformat.pxd @@ -38,7 +38,7 @@ cdef extern from "libavformat/avformat.h" nogil: AVRational sample_aspect_ratio cdef struct AVChapter: - int id + int64_t id int64_t start int64_t end AVRational time_base From acde0d32d7a3118a9200446fda308521d7e0a515 Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Tue, 16 Jun 2026 02:06:54 -0400 Subject: [PATCH 4/5] Fix MSVC narrowing warnings in pyio - PyIOFile.pos is a file position; declare it int64_t instead of long so it doesn't truncate past 2GB on Win64 (C4244 on pos = / += offset) - pyio_read_gil: explicit int cast on the len(res) return (C4244) --- av/container/pyio.pxd | 2 +- av/container/pyio.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/av/container/pyio.pxd b/av/container/pyio.pxd index 80edc8a6b..c1f91b7b6 100644 --- a/av/container/pyio.pxd +++ b/av/container/pyio.pxd @@ -20,5 +20,5 @@ cdef class PyIOFile: # Custom IO for above. cdef lib.AVIOContext *iocontext cdef unsigned char *buffer - cdef long pos + cdef int64_t pos cdef bint pos_is_valid diff --git a/av/container/pyio.py b/av/container/pyio.py index d5c420ea4..34a497246 100644 --- a/av/container/pyio.py +++ b/av/container/pyio.py @@ -109,7 +109,7 @@ def pyio_read_gil(opaque: cython.p_void, buf: Buf, buf_size: cython.int) -> cyth self.pos += len(res) if not res: return lib.AVERROR_EOF - return len(res) + return cython.cast(cython.int, len(res)) except Exception: return stash_exception() From 3dec0b86551059ebaf96baa06dcaa526e40f2b31 Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Tue, 16 Jun 2026 02:12:36 -0400 Subject: [PATCH 5/5] Fix remaining MSVC warnings --- av/container/output.py | 2 +- av/sidedata/sidedata.py | 2 +- av/subtitles/codeccontext.py | 2 +- av/video/format.py | 2 +- include/avcodec.pxd | 2 +- include/avformat.pxd | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/av/container/output.py b/av/container/output.py index 4a9de9f73..c17b32ba4 100644 --- a/av/container/output.py +++ b/av/container/output.py @@ -383,7 +383,7 @@ def add_attachment(self, name: str, mimetype: str, data: bytes): buf[i] = data[i] buf[payload_size] = 0 stream.codecpar.extradata = cython.cast(cython.p_uchar, buf) - stream.codecpar.extradata_size = payload_size + stream.codecpar.extradata_size = cython.cast(cython.int, payload_size) # Wrap as user-land stream. meta_ptr = cython.address(stream.metadata) diff --git a/av/sidedata/sidedata.py b/av/sidedata/sidedata.py index f19aeac06..d0fa7b0d1 100644 --- a/av/sidedata/sidedata.py +++ b/av/sidedata/sidedata.py @@ -109,7 +109,7 @@ def __init__(self, frame: Frame): self._by_index: list = [] self._by_type: dict = {} - i: cython.Py_ssize_t + i: cython.int data: SideData for i in range(self.frame.ptr.nb_side_data): diff --git a/av/subtitles/codeccontext.py b/av/subtitles/codeccontext.py index acad69fb7..618badfb1 100644 --- a/av/subtitles/codeccontext.py +++ b/av/subtitles/codeccontext.py @@ -44,7 +44,7 @@ def subtitle_header(self, data: bytes | None) -> None: if not self.ptr.subtitle_header: raise MemoryError("Cannot allocate subtitle_header") memcpy(self.ptr.subtitle_header, source.ptr, source.length) - self.ptr.subtitle_header_size = source.length + self.ptr.subtitle_header_size = cython.cast(cython.int, source.length) self.subtitle_header_set = True def __dealloc__(self) -> None: diff --git a/av/video/format.py b/av/video/format.py index 654f0f7fe..3ab505051 100644 --- a/av/video/format.py +++ b/av/video/format.py @@ -143,7 +143,7 @@ def chroma_height(self, luma_height: cython.int = 0): @cython.final @cython.cclass class VideoFormatComponent: - def __cinit__(self, format: VideoFormat, index: cython.size_t): + def __cinit__(self, format: VideoFormat, index: cython.uint): self.format = format self.index = index self.ptr = cython.address(format.ptr.comp[index]) diff --git a/include/avcodec.pxd b/include/avcodec.pxd index 4e43b5bf1..5671caf41 100644 --- a/include/avcodec.pxd +++ b/include/avcodec.pxd @@ -338,7 +338,7 @@ cdef extern from "libavcodec/avcodec.h" nogil: cdef struct AVFrameSideData: AVFrameSideDataType type uint8_t *data - int size + size_t size AVDictionary *metadata # See: http://ffmpeg.org/doxygen/trunk/structAVFrame.html diff --git a/include/avformat.pxd b/include/avformat.pxd index 06262c41a..54103f723 100644 --- a/include/avformat.pxd +++ b/include/avformat.pxd @@ -154,7 +154,7 @@ cdef extern from "libavformat/avformat.h" nogil: char filename int64_t start_time int64_t duration - int bit_rate + int64_t bit_rate int flags AVCodecID audio_codec_id AVCodecID video_codec_id