From 3eb06cf431b23e256fc27d36e61d26f85e1f0b09 Mon Sep 17 00:00:00 2001 From: Tingzhong Luo Date: Fri, 25 Nov 2022 16:20:47 +0800 Subject: [PATCH] winspool: Check dmSize in IsValidDevmodeW(). --- dlls/winspool.drv/info.c | 6 ++++-- dlls/winspool.drv/tests/info.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c index 54ecb81d3be..7e1e6138ff2 100644 --- a/dlls/winspool.drv/info.c +++ b/dlls/winspool.drv/info.c @@ -1927,12 +1927,14 @@ BOOL WINAPI IsValidDevmodeW(PDEVMODEW dm, SIZE_T size) #undef F_SIZE }; int i; + const DWORD fields_off = FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dm->dmFields); if (!dm) return FALSE; - if (size < FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dm->dmFields)) return FALSE; + if (size < fields_off) return FALSE; + if (dm->dmSize < fields_off || size < dm->dmSize + dm->dmDriverExtra) return FALSE; for (i = 0; i < ARRAY_SIZE(map); i++) - if ((dm->dmFields & map[i].flag) && size < map[i].size) + if ((dm->dmFields & map[i].flag) && dm->dmSize < map[i].size) return FALSE; return TRUE; diff --git a/dlls/winspool.drv/tests/info.c b/dlls/winspool.drv/tests/info.c index 92b042e354a..52849277c4c 100644 --- a/dlls/winspool.drv/tests/info.c +++ b/dlls/winspool.drv/tests/info.c @@ -3046,6 +3046,26 @@ static void test_IsValidDevmodeW(void) { DM_NUP, FIELD_OFFSET(DEVMODEW, u2.dmNup) + 4, TRUE }, }; + static const struct + { + DWORD dmSize; + DWORD dmDriverExtra; + DWORD bufSize; + BOOL ret; + } size_test[] = + { + { FIELD_OFFSET(DEVMODEW, dmFields) + 3, 1, FIELD_OFFSET(DEVMODEW, dmFields) + 4, FALSE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 4, 1, FIELD_OFFSET(DEVMODEW, dmFields) + 8, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 4, 2, FIELD_OFFSET(DEVMODEW, dmFields) + 8, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 4, 3, FIELD_OFFSET(DEVMODEW, dmFields) + 8, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 4, 4, FIELD_OFFSET(DEVMODEW, dmFields) + 8, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 4, 5, FIELD_OFFSET(DEVMODEW, dmFields) + 8, FALSE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 12, 1, FIELD_OFFSET(DEVMODEW, dmFields) + 16, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 12, 2, FIELD_OFFSET(DEVMODEW, dmFields) + 16, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 12, 3, FIELD_OFFSET(DEVMODEW, dmFields) + 16, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 12, 4, FIELD_OFFSET(DEVMODEW, dmFields) + 16, TRUE }, + { FIELD_OFFSET(DEVMODEW, dmFields) + 12, 5, FIELD_OFFSET(DEVMODEW, dmFields) + 16, FALSE }, + }; DEVMODEW dm; int i; BOOL ret; @@ -3064,6 +3084,17 @@ static void test_IsValidDevmodeW(void) dm.dmFields = test[i].dmFields; ret = IsValidDevmodeW(&dm, dm.dmSize); ok(ret == test[i].ret, "%d: got %d\n", i, ret); + ret = IsValidDevmodeW(&dm, dm.dmSize + 4); + ok(ret == test[i].ret, "%d: got %d\n", i, ret); + } + + dm.dmFields = 0; + for (i = 0; i < ARRAY_SIZE(size_test); i++) + { + dm.dmSize = size_test[i].dmSize; + dm.dmDriverExtra = size_test[i].dmDriverExtra; + ret = IsValidDevmodeW(&dm, size_test[i].bufSize); + ok(ret == size_test[i].ret, "%d: got %d\n", i, ret); } }