| Title | FastStone Image Viewer 8.5 Out-of-Bounds Read |
|---|
| Description | Researcher: Jackson Stone
VULNERABILITY RESEARCH REPORT
• Target Product: FastStone Image Viewer
• Tested Version: 8.5 (Current Release)
• Vulnerability Class: Heap-Based Out-of-Bounds Read (CWE-125) / Off-by-One Array Boundary Indexing (CWE-193)
• Impact Profile: Memory Corruption, Information Disclosure via Resampling Pipelines, or Deterministic Application Faults under PageHeap/AppVerifier environments.
1. EXECUTIVE SUMMARY
An un-clamped boundary-calculation flaw exists within the image downsampling subsystems of FastStone Image Viewer 8.5. When computing column and row resampling metadata vectors for the Box-Average scaling branch, floating-point truncation calculations evaluate to exactly the maximum source boundaries (src_width / src_height).
Because internal processing buffers are zero-indexed, indexing an array at its literal maximum dimension points exactly one element past the allocated heap buffer boundary. This causes the application to continuously read adjacent heap memory contents and process them into the visible image accumulation buffer.
2. ROOT CAUSE & ARCHITECTURAL MECHANISM
During an image scale-down request where dst_width / src_width <= threshold, execution branches into the box-average downsampler engine (FUN_0062d96c).
The routine manages three destination-sized allocation tracking arrays (iVar6, iVar7, and iVar8 — sized at dst_width * 4 bytes). The iVar8 array tracks the bounding end_x index for each destination pixel column.
local_44 = *(int *)(iVar7 + iVar10 * 4); // start_x index in src
iVar16 = *(int *)(iVar8 + iVar10 * 4); // end_x index in src (Missing Bounds Clamp!)
if (local_44 <= iVar16) {
iVar16 = (iVar16 - local_44) + 1;
do {
// iVar2 points to current source row memory segment
iVar13 = iVar13 + (uint)*(byte *)(iVar2 + local_44);
local_4c = local_4c + 1;
local_44 = local_44 + 1;
iVar16 = iVar16 + -1;
} while (iVar16 != 0);
}
The FPU Off-by-One Derivation:
1. Unlike the UPSCALE logic branch in the same module, which passes explicitly clamped inputs normalized to src_width - 1, the downsampling initialization path passes targets normalized against target destination structures (dst_width - 1).
2. 2. When the resampling array builder hits the absolute edge of the loop iteration where dst_col equals (dst_width - 1), the floating-point calculation evaluates the right-hand boundary condition. Substituting the values shows that (dst_col + 1) * src_width / dst_width simplifies exactly to dst_width * src_width / dst_width, which equals src_width.
3. The internal FPU sequence (FUN_00402fc4 pop operation) floors this exact boundary result to an integer, yielding exactly src_width.
4. Because FUN_00613034 is merely an optimized inline min(a, b) macro that validates relative input sizes rather than testing geometry array limits, the raw value src_width is written into the iVar8 map table unchecked.
3. DUAL-AXIS SYMMETRY (MULTIPLIER VECTOR)
The vulnerability is not isolated to horizontal column lookups. Downstream within FUN_0062d96c, a structurally identical box-average iteration is executed vertically to step across image rows. This path relies on an identical un-clamped FPU indexing map, exposing a parallel memory leak path along the vertical coordinate axis:
if (iVar3 <= iVar15) { // start_y <= end_y (un-clamped vs src_height)
do {
iVar13 = iVar13 + (uint)*(byte*)(*(int*)(iVar2 + local_48 * 4) + iVar16);
// ...
} while (...);
} |
|---|
| User | jacksonstone (UID 56993) |
|---|
| Submission | 10/05/2026 09:45 (28 days ago) |
|---|
| Moderation | 10/26/2026 11:14 (21 days later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 426360 [FastStone Image Viewer up to 8.5 Box-Average Downsampler Engine FUN_0062d96c out-of-bounds] |
|---|
| Points | 17 |
|---|