Esme Povirk (@madewokherd) commented about dlls/sane.ds/ds_image.c:
+ struct read_data_params params = { NULL, activeDS.frame_params.bytes_per_line, &retlen }; + + if (y >= -header->biHeight) + { + TRACE("Data source transfers more lines than expected. Extend DIB to %ld lines\n", (-header->biHeight)+1000); + GlobalUnlock(hDIB); + + dib_bytes += 1000 * dib_bytes_per_line; + hDIB = GlobalReAlloc(hDIB, dib_bytes + sizeof(*header) + color_size, GMEM_MOVEABLE); + + if (!hDIB) + { + SANE_Cancel(); + activeDS.twCC = TWCC_LOWMEMORY; + activeDS.currentState = 6; + return TWRC_FAILURE; hDIB needs to be freed in this case, but we lost its value by assigning from GlobalReAlloc. With GMEM_MOVEABLE, that assignment isn't necessary, so we could just do a check here like `if (!GlobalReAlloc(...))`.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9397#note_121535