From f144c67676802ad98c4db3edff6f7d2585b0b7b4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 25 Jan 2021 14:58:52 +0100 Subject: [PATCH] ImDrawList: fixed AddCircle, AddCircleFilled buffer read overflow with (rad > 0.0f && rad < 1.0f && num_segments == 0). (#3738) Amend 051ce076. Maximum cached count becomes 63 instead of 64. --- docs/CHANGELOG.txt | 12 ++++++++++++ imgui.cpp | 2 +- imgui.h | 2 +- imgui_draw.cpp | 6 +++--- imgui_internal.h | 3 ++- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4c928b7bf..1b66f1b9c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -31,10 +31,22 @@ HOW TO UPDATE? - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.8X (In Progress) +----------------------------------------------------------------------- + +Other Changes: + +- ImDrawList: fixed AddCircle()/AddCircleFilled() with (rad > 0.0f && rad < 1.0f && num_segments == 0). (#3738) + Would lead to a buffer read overflow. + + ----------------------------------------------------------------------- VERSION 1.80 (Released 2021-01-21) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.80 + Breaking Changes: - Added imgui_tables.cpp file! Manually constructed project files will need the new file added! (#3740) diff --git a/imgui.cpp b/imgui.cpp index b3c42dac5..cd1be7b21 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1130,7 +1130,7 @@ void ImGuiIO::ClearInputCharacters() ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments) { - IM_ASSERT(num_segments > 0); // Use ImBezierClosestPointCasteljau() + IM_ASSERT(num_segments > 0); // Use ImBezierCubicClosestPointCasteljau() ImVec2 p_last = p1; ImVec2 p_closest; float p_closest_dist2 = FLT_MAX; diff --git a/imgui.h b/imgui.h index 99f03dec3..3ce67a54e 100644 --- a/imgui.h +++ b/imgui.h @@ -59,7 +59,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.80" -#define IMGUI_VERSION_NUM 18000 +#define IMGUI_VERSION_NUM 18001 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8a6756649..5f2a20c0a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -377,7 +377,7 @@ void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error) CircleSegmentMaxError = max_error; for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++) { - const float radius = i + 1.0f; + const float radius = (float)i; const int segment_count = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError); CircleSegmentCounts[i] = (ImU8)ImMin(segment_count, 255); } @@ -1278,7 +1278,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu if (num_segments <= 0) { // Automatic segment count - const int radius_idx = (int)radius - 1; + const int radius_idx = (int)radius; if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value else @@ -1308,7 +1308,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, if (num_segments <= 0) { // Automatic segment count - const int radius_idx = (int)radius - 1; + const int radius_idx = (int)radius; if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value else diff --git a/imgui_internal.h b/imgui_internal.h index dff845a63..bcfb675f7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -610,6 +610,7 @@ struct IMGUI_API ImChunkStream //----------------------------------------------------------------------------- // ImDrawList: Helper function to calculate a circle's segment count given its radius and a "maximum error" value. +// FIXME: the minimum number of auto-segment may be undesirably high for very small radiuses (e.g. 1.0f) #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 12 #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512 #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp((int)((IM_PI * 2.0f) / ImAcos(((_RAD) - (_MAXERROR)) / (_RAD))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) @@ -633,7 +634,7 @@ struct IMGUI_API ImDrawListSharedData // [Internal] Lookup tables ImVec2 ArcFastVtx[12 * IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER]; // FIXME: Bake rounded corners fill/borders in atlas - ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius (array index + 1) before we calculate it dynamically (to avoid calculation overhead) + ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead) const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas ImDrawListSharedData();