Projects
Staging
libde265
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 20
View file
libde265.changes
Changed
@@ -1,4 +1,67 @@ ------------------------------------------------------------------- +Thu Sep 3 06:04:55 UTC 2026 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.1.2: + + This is a security and bugfix release. It is ABI- and + API-compatible with v1.1.1 and is a drop-in replacement. Two + enum values were added: DE265_ERROR_INVALID_ARGUMENT and + DE265_WARNING_SLICE_SEGMENT_ADDRESS_NOT_INCREASING. + + Security fixes: (CVE numbers will be added when assigned.) + - CVE-2026-XXXXX (GHSA-xp3h-6f5r-8cxp) Heap use-after-free and + double free in multi-threaded (WPP) decoding. A crafted + stream whose slice segments repeat or rewind their + slice_segment_address within a picture re-ran CTB rows that + were already marked finished, so the CABAC context handoff + between rows was no longer ordered and the shared context + table was released twice. Slice segments that do not follow + the previous one in tile-scan order are now rejected with the + new warning + DE265_WARNING_SLICE_SEGMENT_ADDRESS_NOT_INCREASING, and the + WPP row progress is reset for each slice segment. (medium) + - CVE-2026-XXXXX (GHSA-mm7m-v26f-wf8x) Heap use-after-free + after de265_reset(): the pointer to the previous slice header + was left dangling when the DPB was cleared, and a dependent + slice pushed after the reset copied from freed memory. + (medium) + + Hardening: + - de265_push_NAL() rejects NAL units shorter than the two-byte + NAL unit header (including negative lengths) with the new + DE265_ERROR_INVALID_ARGUMENT instead of calling memcpy() with + a NULL destination and then aborting the decode + - SEI parsing: the overflow guard on the accumulated + payload_size compared the wrong variable and could never + trigger, so a crafted size could wrap around silently + - The per-CTB progress counters and the image integrity flag + are atomic with acquire/release ordering; ThreadSanitizer + reported data races on them with several worker threads + + Bug fixes: + - Regression since v1.0.17: a cu_qp_delta of -26 was rejected + as out of range although the allowed range is asymmetric and + -26 is valid. Real-world encoders emit this value; the + rejection aborted the slice and corrupted every picture of + the affected IDR period + - Regression since v1.0.17: an out-of-range value in the + advisory VUI fields (bitstream_restriction(), + chroma_sample_loc_type_*) rejected the whole SPS, so HEIF + images from some consumer encoders could not be decoded at + all. These fields are never used in the decoding process; + they are now clamped with a warning as in v1.0.16. Malformed + exp-Golomb codes are still a hard error + - 16-bit decoding: the residual of 4x4 intra luma blocks (DST) + was clipped to 16 bits although it needs 17 bits at bit depth + 16, corrupting those blocks and everything intra-predicted + from them. Output is now identical to the HM reference + decoder; bit depths up to 15 were not affected + - MSVC: the visibility attribute is only used with GCC and + Clang, fixing the static build with MSVC + - CMake: building sherlock265 together with the library + silently disabled the hidden symbol visibility introduced in + v1.1.1. sherlock265 only uses exported symbols, so it no + longer forces full visibility, and the configure output now + states why symbols are hidden or exported. + FORCE_FULL_VISIBILITY is documented in the README + +------------------------------------------------------------------- Tue Jun 16 07:40:59 UTC 2026 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.1.1:
View file
libde265.spec
Changed
@@ -18,7 +18,7 @@ %define so_ver 0 Name: libde265 -Version: 1.1.1 +Version: 1.1.2 Release: 0 Summary: Open H.265 video codec implementation License: LGPL-3.0-only
View file
libde265-1.1.2.tar.gz/.well-known
Added
+(directory)
View file
libde265-1.1.2.tar.gz/.well-known/funding-manifest-urls
Added
@@ -0,0 +1,2 @@ +https://github.com/strukturag/libheif/blob/master/funding.json +https://raw.githubusercontent.com/strukturag/libheif/master/funding.json
View file
libde265-1.1.1.tar.gz/CMakeLists.txt -> libde265-1.1.2.tar.gz/CMakeLists.txt
Changed
@@ -2,7 +2,7 @@ project (libde265 LANGUAGES C CXX - VERSION 1.1.1 + VERSION 1.1.2 ) # Auto-compute BCD-encoded numeric version from project version. @@ -35,7 +35,7 @@ # Programs linked against libde265.so.0 will work with any libde265.so.0.x.y. # set(DE265_SOVERSION 0) -set(DE265_LIBRARY_VERSION "0.2.1") +set(DE265_LIBRARY_VERSION "0.2.2") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -202,22 +202,24 @@ # Hiding the library's non-API symbols turns cross-translation-unit calls inside # libde265 from indirect PLT/GOT dispatch into direct calls — a measurable win # on the hot CABAC decode path — and shrinks the dynamic symbol table. Only the -# symbols tagged LIBDE265_API (the public de265_*/en265_* C API) stay exported. +# symbols tagged LIBDE265_API (the public de265_*/en265_* C API and the draw_* +# helpers used by sherlock265) stay exported. # # By default we reduce visibility for optimized (non-Debug) builds and keep # every symbol exported for Debug builds, so a debug build stays fully available -# for introspection. The encoder CLI, sherlock265 and the dev tools all link -# against *internal* (non-API) symbols of the library, so hiding would break -# their link; visibility is therefore never reduced when any of those is built. +# for introspection. The encoder CLI and the dev tools link against *internal* +# (non-API) symbols of the library, so hiding would break their link; +# visibility is therefore never reduced when either of those is built. +# (sherlock265 only uses LIBDE265_API symbols and does not affect this.) # # Set FORCE_FULL_VISIBILITY=ON to override the default and export all symbols # even from an optimized build. option(FORCE_FULL_VISIBILITY - "Export all symbols, even from optimized builds (default: hide non-API symbols in optimized builds without the encoder/tools)" + "Export all symbols, even from optimized builds (default: hide non-API symbols in optimized builds without the encoder/dev-tools)" OFF) set(_de265_internal_consumers OFF) -if(ENABLE_ENCODER OR ENABLE_SHERLOCK265 OR ENABLE_INTERNAL_DEVELOPMENT_TOOLS) +if(ENABLE_ENCODER OR ENABLE_INTERNAL_DEVELOPMENT_TOOLS) set(_de265_internal_consumers ON) endif() @@ -230,12 +232,18 @@ endif() set(DE265_REDUCED_VISIBILITY OFF) -if(_de265_optimized_build AND NOT _de265_internal_consumers AND NOT FORCE_FULL_VISIBILITY) +if(FORCE_FULL_VISIBILITY) + message(STATUS "Symbol visibility: all symbols exported (FORCE_FULL_VISIBILITY=ON)") +elseif(_de265_internal_consumers) + message(STATUS "Symbol visibility: all symbols exported (enc265 / dev-tools need internal symbols)") +elseif(NOT _de265_optimized_build) + message(STATUS "Symbol visibility: all symbols exported (Debug build or no CMAKE_BUILD_TYPE)") +else() set(DE265_REDUCED_VISIBILITY ON) set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) - message(STATUS "Reduced symbol visibility enabled (only LIBDE265_API symbols exported)") + message(STATUS "Symbol visibility: hidden (only LIBDE265_API symbols exported)") endif() add_subdirectory (libde265)
View file
libde265-1.1.1.tar.gz/README.md -> libde265-1.1.2.tar.gz/README.md
Changed
@@ -100,6 +100,15 @@ -DENABLE_SHERLOCK265=off Do not build the sherlock265 visual inspection program. </pre> +Optimized (non-Debug) builds hide all symbols except the public API, which makes +the decoder faster and the shared library smaller. The encoder and the internal +development tools need the internal symbols, so enabling them keeps everything +exported. To export all symbols even from an optimized decoder-only build, run +`cmake` with +<pre> + -DFORCE_FULL_VISIBILITY=on +</pre> + Additional logging information can be turned on and off using these `./configure` flags: <pre> -DDE265_LOG_LEVEL={error;info;debug;trace} @@ -150,7 +159,7 @@ ## Packaging status -!libde265 packaging status(https://repology.org/badge/vertical-allrepos/libde265.svg?exclude_unsupported=1&columns=3&exclude_sources=modules,site&header=libde265%20packaging%20status)(https://repology.org/project/libheif/versions) +!libde265 packaging status(https://repology.org/badge/vertical-allrepos/libde265.svg?exclude_unsupported=1&columns=3&exclude_sources=modules,site&header=libde265%20packaging%20status)(https://repology.org/project/libde265/versions) License
View file
libde265-1.1.1.tar.gz/libde265/CMakeLists.txt -> libde265-1.1.2.tar.gz/libde265/CMakeLists.txt
Changed
@@ -125,7 +125,7 @@ # --- debug output -set(LOG_LEVELS error info debug trace) +set(LOG_LEVELS none error info debug trace) set(DE265_LOG_LEVEL "error" CACHE STRING "Log level (${LOG_LEVELS})") set_property(CACHE DE265_LOG_LEVEL PROPERTY STRINGS ${LOG_LEVELS}) @@ -133,7 +133,10 @@ message(FATAL_ERROR "DE265_LOG_LEVEL has to be one of: ${LOG_LEVELS}") endif () -if (DE265_LOG_LEVEL MATCHES "error") +if (DE265_LOG_LEVEL STREQUAL "none") + # No logging compiled in — all logerror/loginfo/etc. calls become no-op + # macros via the #else branches in libde265/util.h. +elseif (DE265_LOG_LEVEL MATCHES "error") target_compile_definitions(de265 PRIVATE DE265_LOG_ERROR) elseif (DE265_LOG_LEVEL MATCHES "info") target_compile_definitions(de265 PRIVATE DE265_LOG_ERROR DE265_LOG_INFO)
View file
libde265-1.1.1.tar.gz/libde265/de265.cc -> libde265-1.1.2.tar.gz/libde265/de265.cc
Changed
@@ -84,6 +84,7 @@ case DE265_ERROR_IMAGE_BUFFER_FULL: return "DPB/output queue full"; case DE265_ERROR_IMAGE_SIZE_EXCEEDS_SECURITY_LIMIT: return "image size exceeds security limit"; case DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT: return "NAL unit size exceeds security limit"; + case DE265_ERROR_INVALID_ARGUMENT: return "invalid argument"; case DE265_ERROR_CANNOT_START_THREADPOOL: return "cannot start decoding threads"; case DE265_ERROR_LIBRARY_INITIALIZATION_FAILED: return "global library initialization failed"; case DE265_ERROR_LIBRARY_NOT_INITIALIZED: return "cannot free library data (not initialized"; @@ -184,6 +185,8 @@ return "Rice parameter or StatCoeff out of range, clamped"; case DE265_WARNING_MAX_NUMBER_OF_SEI_MESSAGES_EXCEEDED: return "number of SEI messages exceeds security limit, dropped"; + case DE265_WARNING_SLICE_SEGMENT_ADDRESS_NOT_INCREASING: + return "slice segment address not increasing within picture, slice segment dropped"; default: return "unknown error"; }
View file
libde265-1.1.1.tar.gz/libde265/de265.h -> libde265-1.1.2.tar.gz/libde265/de265.h
Changed
@@ -40,7 +40,8 @@ #else #define LIBDE265_API __declspec(dllimport) #endif -#elif HAVE_VISIBILITY +#elif (defined(__GNUC__) || defined(__clang__)) && HAVE_VISIBILITY + // GCC-style visibility attributes #ifdef LIBDE265_EXPORTS #define LIBDE265_API __attribute__((__visibility__("default"))) #else @@ -97,6 +98,7 @@ DE265_ERROR_UNSPECIFIED_DECODING_ERROR=18, DE265_ERROR_IMAGE_SIZE_EXCEEDS_SECURITY_LIMIT=19, DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT=20, + DE265_ERROR_INVALID_ARGUMENT=21, // --- errors that should become obsolete in later libde265 versions --- @@ -143,7 +145,8 @@ DE265_WARNING_INVALID_SLICE_HEADER_INDEX_ACCESS=1033, DE265_WARNING_INVALID_TU_BLOCK_SPLIT=1034, DE265_WARNING_RICE_PARAMETER_OUT_OF_RANGE=1035, - DE265_WARNING_MAX_NUMBER_OF_SEI_MESSAGES_EXCEEDED=1036 + DE265_WARNING_MAX_NUMBER_OF_SEI_MESSAGES_EXCEEDED=1036, + DE265_WARNING_SLICE_SEGMENT_ADDRESS_NOT_INCREASING=1037 } de265_error; LIBDE265_API const char* de265_get_error_text(de265_error err); @@ -265,6 +268,9 @@ /* Push a complete NAL unit without startcode into the decoder. The data must still contain all stuffing-bytes. This function only pushes data into the decoder, nothing will be decoded. + The NAL unit must at least contain the two-byte NAL unit header. A shorter + (or negative) length is rejected with DE265_ERROR_INVALID_ARGUMENT and nothing + is pushed. */ LIBDE265_API de265_error de265_push_NAL(de265_decoder_context*, const void* data, int length, de265_PTS pts, void* user_data);
View file
libde265-1.1.1.tar.gz/libde265/decctx.cc -> libde265-1.1.2.tar.gz/libde265/decctx.cc
Changed
@@ -202,6 +202,16 @@ img = nullptr; + // Drop the back-reference to the previous picture's slice header before the + // DPB is cleared below. dpb.clear() releases the images, which own and free + // their slice_segment_header structs (see de265_image::release()). Leaving + // previous_slice_header pointing into that freed storage lets a following + // dependent slice read from it (slice.cc: '*this = *ctx->previous_slice_header'), + // a heap-use-after-free. This mirrors the in-stream new-picture guard in + // read_slice_NAL(): only a slice header still retained by a live image may + // remain as previous_slice_header. + previous_slice_header = nullptr; + // TODO: remove all pending image_units @@ -450,6 +460,49 @@ return DE265_OK; } +bool decoder_context::slice_segment_order_is_valid(image_unit* imgunit, + const slice_segment_header* shdr) +{ + // Nothing to compare against for the first slice segment of the picture. + if (imgunit->slice_units.empty() || imgunit->img == nullptr) { + return true; + } + + de265_image* img = imgunit->img; + const pic_parameter_set& pps = img->get_pps(); + if (!pps.scan) { + return true; + } + + const std::vector<uint32_t>& RStoTS = pps.scan->CtbAddrRStoTS; + + uint32_t prevAddr = imgunit->slice_units.back()->shdr->slice_segment_address; + uint32_t thisAddr = shdr->slice_segment_address; + + if (prevAddr >= RStoTS.size() || thisAddr >= RStoTS.size()) { + add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID, false); + img->integrity = INTEGRITY_DECODING_ERRORS; + return false; + } + + // H.265 7.4.2.4.5: the slice segments of a coded picture shall be ordered by + // increasing tile-scan address of their first CTB, and (7.4.7.1) no two slice + // segments of a picture share a slice_segment_address. A slice segment that + // repeats or goes back to an earlier address would re-decode CTBs that were + // already decoded. In WPP mode the progress of those CTBs is already marked + // as finished, so the row tasks of the offending slice segment would not wait + // for the row above and would race with each other on the CTB metadata and + // the reconstructed pixels. Drop such slice segments. + if (RStoTSthisAddr <= RStoTSprevAddr) { + add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_NOT_INCREASING, false); + img->integrity = INTEGRITY_DECODING_ERRORS; + return false; + } + + return true; +} + + de265_error decoder_context::read_slice_NAL(bitreader& reader, NAL_unit* nal, nal_header& nal_hdr) { logdebug(LogHeaders,"---> read slice segment header\n"); @@ -516,7 +569,8 @@ // --- add slice to current picture --- - if ( ! image_units.empty() ) { + if ( ! image_units.empty() && + slice_segment_order_is_valid(image_units.back(), shdr) ) { // Hand the slice header to the picture (which takes ownership and frees it // on release). Only do this when there is an active image unit to decode @@ -873,6 +927,24 @@ return DE265_WARNING_SLICEHEADER_INVALID; } + // Reset the decoding progress of all CTBs that the row tasks of this slice + // segment are going to decode (from its first CTB to the end of its last + // CTB row). Their progress may already be marked as finished, e.g. by a + // preceding slice segment whose entry points claimed more rows than its + // data covered, because a row task marks the rest of its row as finished + // when it fails. Stale progress would let the row tasks of this slice + // segment skip waiting for the row above and race with each other on the + // CTB metadata and the reconstructed pixels. No task is running on the + // image at this point (asserted above), so nobody can be waiting on the + // CTBs that are reset here. + { + uint32_t endCtb = std::min<uint32_t>((uint32_t)(ctbRow + nRows) * ctbsWidth, + img->number_of_ctbs()); + for (uint32_t ctb = ctbAddrRS; ctb < endCtb; ctb++) { + img->ctb_progressctb.reset(CTB_PROGRESS_NONE); + } + } + for (uint16_t entryPt=0;entryPt<nRows;entryPt++) { // entry points other than the first start at CTB rows if (entryPt>0) {
View file
libde265-1.1.1.tar.gz/libde265/decctx.h -> libde265-1.1.2.tar.gz/libde265/decctx.h
Changed
@@ -37,6 +37,7 @@ #include <array> #include <memory> +#include <mutex> constexpr int DE265_MAX_VPS_SETS = 16; // this is the maximum as defined in the standard constexpr int DE265_MAX_SPS_SETS = 16; // this is the maximum as defined in the standard @@ -261,7 +262,20 @@ /* Saved context models for WPP. There is one saved model for the initialization of each CTB row. - The array is unused for non-WPP streams. */ + The array is unused for non-WPP streams. + + Threading: context_model_table is a reference-counted handle (model + pointer plus refcount pointer) that is not thread-safe, so each slot is + touched by exactly one producer and one consumer and never concurrently. + The row task of row N stores into ctx_modelsN after decoding CTB x=1 + and only then signals CTB_PROGRESS_PREFILTER for that CTB; the row task + of row N+1 waits for that progress before it copies and releases the + slot. The acquire/release ordering of de265_progress_lock makes the + store visible to the consumer, so no lock is needed. This relies on the + wait never being skipped because of stale progress: slice segments must + arrive in increasing address order (slice_segment_order_is_valid()) and + decode_slice_unit_WPP() resets the progress of the rows it schedules + (GHSA-xp3h-6f5r-8cxp). */ std::vector<context_model_table> ctx_models; // TODO: move this into image ? /* Saved StatCoeff (persistent_rice_adaptation state) parallel to ctx_models. @@ -516,6 +530,12 @@ void add_task_decode_slice_segment(thread_context* tctx, bool firstSliceSubstream, uint16_t ctbX, uint16_t ctbY); + /* Check that the slice segment 'shdr' may be appended to 'imgunit', i.e. that + its first CTB follows the previous slice segment of the picture in tile-scan + order (H.265 7.4.2.4.5). Adds a warning and marks the image as faulty when + the slice segment has to be dropped. */ + bool slice_segment_order_is_valid(image_unit* imgunit, const slice_segment_header* shdr); + void mark_whole_slice_as_processed(image_unit* imgunit, slice_unit* sliceunit, int progress);
View file
libde265-1.1.1.tar.gz/libde265/fallback-dct.cc -> libde265-1.1.2.tar.gz/libde265/fallback-dct.cc
Changed
@@ -324,7 +324,8 @@ sum += mat_8_357ji * gyj; } - int out = Clip3(-32768,32767, (sum+rndH)>>postShift); + // no clipping to -32768;32767 required + int out = (sum+rndH)>>postShift; dsty*stride+i = Clip1_8bit(dsty*stride+i + out); @@ -395,7 +396,9 @@ sum += mat_8_357ji * gyj; } - int out = Clip3(-32768,32767, (sum+rndH)>>postShift); + // no clipping to -32768;32767 required + // (at bit depth 16 the residual needs 17 bits and clipping breaks it) + int out = (sum+rndH)>>postShift; dsty*stride+i = Clip_BitDepth(dsty*stride+i + out, bit_depth);
View file
libde265-1.1.1.tar.gz/libde265/image.h -> libde265-1.1.2.tar.gz/libde265/image.h
Changed
@@ -32,6 +32,7 @@ #include <string.h> #include <limits> #include <memory> +#include <atomic> #include "libde265/de265.h" #include "libde265/sps.h" @@ -427,7 +428,8 @@ void* userdata); */ - uint8_t integrity = INTEGRITY_NOT_DECODED; /* Whether an error occurred while the image was decoded. + // Written from several worker threads on error paths, hence atomic. + std::atomic<uint8_t> integrity{INTEGRITY_NOT_DECODED}; /* Whether an error occurred while the image was decoded. When generated, this is initialized to INTEGRITY_CORRECT, and changed on decoding errors. */
View file
libde265-1.1.1.tar.gz/libde265/nal-parser.cc -> libde265-1.1.2.tar.gz/libde265/nal-parser.cc
Changed
@@ -92,7 +92,9 @@ if (!resize(data_size + n)) { return false; } - memcpy(nal_data + data_size, in_data, n); + if (n > 0) { + memcpy(nal_data + data_size, in_data, n); + } data_size += n; return true; } @@ -102,7 +104,9 @@ if (!resize(n)) { return false; } - memcpy(nal_data, in_data, n); + if (n > 0) { + memcpy(nal_data, in_data, n); + } data_size = n; return true; } @@ -400,6 +404,14 @@ // Cannot use byte-stream input and NAL input at the same time. assert(pending_input_NAL == nullptr); + // A NAL unit must at least contain its two-byte header. Reject anything shorter + // (including a negative length) before touching any state: a zero-length unit + // would otherwise end up as a memcpy() with a NULL destination and, once queued, + // would fail header parsing in decode_NAL() and abort decoding of the stream. + if (len < 2) { + return DE265_ERROR_INVALID_ARGUMENT; + } + end_of_frame = false; // enforce the maximum NAL size to bound memory usage
View file
libde265-1.1.1.tar.gz/libde265/sei.cc -> libde265-1.1.2.tar.gz/libde265/sei.cc
Changed
@@ -388,7 +388,7 @@ { uint32_t byte = reader->get_bits(8); - if (MAX_SEI_SIZE - byte < payload_type) { + if (MAX_SEI_SIZE - byte < payload_size) { return DE265_ERROR_CANNOT_PROCESS_SEI; }
View file
libde265-1.1.1.tar.gz/libde265/slice.cc -> libde265-1.1.2.tar.gz/libde265/slice.cc
Changed
@@ -3632,8 +3632,9 @@ cu_qp_delta_sign = tctx->cabac_decoder.decode_bypass(); } - // CuQpDeltaVal shall be in -(26 + QpBdOffsetY/2), 25 + QpBdOffsetY/2 (Sec. 7.4.9.10) - int maxCuQpDeltaAbs = 25 + tctx->img->get_sps().QpBdOffset_Y / 2; + // CuQpDeltaVal shall be in -(26 + QpBdOffsetY/2), +(25 + QpBdOffsetY/2) (Sec. 7.4.9.14). + // Note that the range is asymmetric. + int maxCuQpDeltaAbs = (cu_qp_delta_sign ? 26 : 25) + tctx->img->get_sps().QpBdOffset_Y / 2; if (cu_qp_delta_abs > maxCuQpDeltaAbs) { tctx->decctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; @@ -4757,7 +4758,13 @@ // we have to wait until the context model data is there tctx->img->wait_for_progress(tctx->task, 1, tctx->CtbY - 1,CTB_PROGRESS_PREFILTER); - // copy CABAC model from previous CTB row + // Copy the CABAC model (and StatCoeff state) saved by the row above. + // No lock is needed: the producer stores into ctx_modelsCtbY-1 before + // it signals the progress of CTB (1, CtbY-1), and the acquire load in + // wait_for_progress() above pairs with that release store. The slot has + // exactly one producer and one consumer, and after the copy/release + // below nobody touches it again. See image_unit::ctx_models for why a + // consumer can never skip this wait. tctx->ctx_model = tctx->imgunit->ctx_models(tctx->CtbY - 1); tctx->imgunit->ctx_models(tctx->CtbY - 1).release(); // not used anymore @@ -4816,6 +4823,12 @@ return Decode_Error; } + // Store an independent copy of the CABAC model (and StatCoeff state) for + // the row below to pick up. This store must stay ahead of the + // set_progress(CTB_PROGRESS_PREFILTER) for this CTB further down: that + // release store publishes the slot to the consumer row task, which waits + // for CTB (1, ctby) with an acquire load before reading it. No lock is + // needed, see image_unit::ctx_models. tctx->imgunit->ctx_modelsctby = tctx->ctx_model; tctx->imgunit->ctx_modelsctby.decouple(); // store an independent copy
View file
libde265-1.1.1.tar.gz/libde265/threads.cc -> libde265-1.1.2.tar.gz/libde265/threads.cc
Changed
@@ -31,7 +31,7 @@ de265_progress_lock::de265_progress_lock() { - mProgress = 0; + mProgress.store(0, std::memory_order_relaxed); } de265_progress_lock::~de265_progress_lock() @@ -40,12 +40,15 @@ void de265_progress_lock::wait_for_progress(int progress) { - if (mProgress >= progress) { + // Fast path: acquire-load pairs with the release-store in set_progress()/ + // increase_progress() so that everything the signalling thread wrote before + // reaching this progress value is visible once we observe it here. + if (mProgress.load(std::memory_order_acquire) >= progress) { return; } std::unique_lock<std::mutex> lock(mutex); - while (mProgress < progress) { + while (mProgress.load(std::memory_order_acquire) < progress) { cond.wait(lock); } } @@ -54,8 +57,8 @@ { std::unique_lock<std::mutex> lock(mutex); - if (progress>mProgress) { - mProgress = progress; + if (progress > mProgress.load(std::memory_order_relaxed)) { + mProgress.store(progress, std::memory_order_release); cond.notify_all(); } @@ -65,13 +68,14 @@ { std::unique_lock<std::mutex> lock(mutex); - mProgress += progress; + mProgress.store(mProgress.load(std::memory_order_relaxed) + progress, + std::memory_order_release); cond.notify_all(); } int de265_progress_lock::get_progress() const { - return mProgress; + return mProgress.load(std::memory_order_acquire); }
View file
libde265-1.1.1.tar.gz/libde265/threads.h -> libde265-1.1.2.tar.gz/libde265/threads.h
Changed
@@ -42,6 +42,7 @@ #endif #endif // _WIN32 +#include <atomic> #include <mutex> #include <condition_variable> #include <thread> @@ -56,10 +57,16 @@ void set_progress(int progress); void increase_progress(int progress); int get_progress() const; - void reset(int value=0) { mProgress=value; } + void reset(int value=0) { mProgress.store(value, std::memory_order_release); } private: - int mProgress; + // Read lock-free on the fast paths of wait_for_progress()/get_progress() + // while written under 'mutex'. It must be atomic so those reads are not a + // data race, and it carries acquire/release ordering so that the state a + // producer wrote before signalling progress (e.g. the saved WPP row context) + // is published to a consumer that observes the progress value without taking + // the mutex (GHSA-xp3h-6f5r-8cxp). + std::atomic<int> mProgress; // private data
View file
libde265-1.1.1.tar.gz/libde265/util.cc -> libde265-1.1.2.tar.gz/libde265/util.cc
Changed
@@ -40,6 +40,10 @@ #ifdef DE265_LOGGING +// I see that there is a data-race when setting the current_poc (#535), +// but this and log_poc_start are mainly there to reduce the log noise during +// debugging. It's nothing that is used in production. +// TODO: this may change if we add frame-parallel decoding. static int current_poc=0; static int log_poc_start=-9999; // frame-numbers can be negative static bool disable_logNUMBER_OF_LogModules;
View file
libde265-1.1.1.tar.gz/libde265/vui.cc -> libde265-1.1.2.tar.gz/libde265/vui.cc
Changed
@@ -33,6 +33,31 @@ (variable) = vlc; +/* Read an advisory ue(v) VUI syntax element. + + A malformed exp-Golomb code (UVLC_ERROR) is a hard error: we lost the bit + position and nothing after it can be parsed. + + A well-formed value that merely exceeds the range allowed by the standard is + only a warning. The chroma siting and bitstream_restriction() elements are + hints for the decoder that are never used in the decoding process, so an + out-of-range value cannot affect correctness or memory safety. Real-world + streams (e.g. HEIF images from consumer encoders) contain such values, so we + clamp to the value the standard infers when the element is absent and keep + parsing instead of rejecting the whole SPS (issue #539). + */ +#define READ_ADVISORY_VLC(variable, maxval, defaultval) \ + if ((vlc = br->get_uvlc()) == UVLC_ERROR) { \ + errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); \ + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; \ + } \ + if (vlc > (maxval)) { \ + errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); \ + vlc = (defaultval); \ + } \ + (variable) = vlc; + + #define NUM_SAR_PRESETS 17 static uint16_t sar_presetsNUM_SAR_PRESETS+12 = { @@ -246,17 +271,8 @@ chroma_loc_info_present_flag = br->get_bits(1); if (chroma_loc_info_present_flag) { - if ((vlc = br->get_uvlc()) == UVLC_ERROR || vlc > 5) { - errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - chroma_sample_loc_type_top_field = vlc; - - if ((vlc = br->get_uvlc()) == UVLC_ERROR || vlc > 5) { - errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - chroma_sample_loc_type_bottom_field = vlc; + READ_ADVISORY_VLC(chroma_sample_loc_type_top_field, 5, 0); + READ_ADVISORY_VLC(chroma_sample_loc_type_bottom_field, 5, 0); } else { chroma_sample_loc_type_top_field = 0; @@ -322,35 +338,12 @@ motion_vectors_over_pic_boundaries_flag = br->get_bits(1); restricted_ref_pic_lists_flag = br->get_bits(1); - if ((vlc = br->get_uvlc()) == UVLC_ERROR || vlc > 4095) { - errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - min_spatial_segmentation_idc = vlc; - - if ((vlc = br->get_uvlc()) == UVLC_ERROR || vlc > 16) { - errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - max_bytes_per_pic_denom = vlc; - - if ((vlc = br->get_uvlc()) == UVLC_ERROR || vlc > 16) { - errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - max_bits_per_min_cu_denom = vlc; - - if ((vlc = br->get_uvlc()) == UVLC_ERROR || vlc > 15) { - errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - log2_max_mv_length_horizontal = vlc; - - if ((vlc = br->get_uvlc()) == UVLC_ERROR || vlc > 15) { - errqueue->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - log2_max_mv_length_vertical = vlc; + // Same defaults as in the else-branch below (the values inferred when absent). + READ_ADVISORY_VLC(min_spatial_segmentation_idc, 4095, 0); + READ_ADVISORY_VLC(max_bytes_per_pic_denom, 16, 2); + READ_ADVISORY_VLC(max_bits_per_min_cu_denom, 16, 1); + READ_ADVISORY_VLC(log2_max_mv_length_horizontal, 15, 15); + READ_ADVISORY_VLC(log2_max_mv_length_vertical, 15, 15); } else { tiles_fixed_structure_flag = false;
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.