[PATCH 0/1] MR9672: win32u: Don't alter memory beyond structure effective size in NtUserEnumDisplaySettings().
From: Paul Gofman <pgofman(a)codeweavers.com> --- dlls/user32/tests/sysparams.c | 53 +++++++++++++++++++++++++++++++++++ dlls/win32u/sysparams.c | 6 ++-- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/dlls/user32/tests/sysparams.c b/dlls/user32/tests/sysparams.c index 0ffa9716be0..501d9afe5ea 100644 --- a/dlls/user32/tests/sysparams.c +++ b/dlls/user32/tests/sysparams.c @@ -3172,6 +3172,7 @@ static void test_EnumDisplaySettings(void) BOOL attached, ret; DISPLAY_DEVICEA dd; DEVMODEA dm, dm2; + unsigned int i; DEVMODEW dmW; HDC hdc; @@ -3233,6 +3234,58 @@ static void test_EnumDisplaySettings(void) ok((dmW.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#lx, got %#lx\n", setting_fields, dmW.dmFields); + memset(&dmW, 0xcc, sizeof(dmW)); + ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &dmW); + ok(ret, "EnumDisplaySettingsW failed, error %#lx\n", GetLastError()); + ok(dmW.dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod), "Expect dmSize %lu, got %u\n", + FIELD_OFFSET(DEVMODEW, dmICMMethod), dmW.dmSize); + ok((dmW.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#lx, got %#lx\n", + setting_fields, dmW.dmFields); + for (i = dmW.dmSize; i < sizeof(DEVMODEW); ++i) + { + if (((BYTE *)&dmW)[i] != 0xcc) + break; + } + ok(i == sizeof(DEVMODEW), "data modified at offset %u.\n", i); + + memset(&dmW, 0xcc, sizeof(dmW)); + ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &dmW); + ok(ret, "EnumDisplaySettingsW failed, error %#lx\n", GetLastError()); + ok(dmW.dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod), "Expect dmSize %lu, got %u\n", + FIELD_OFFSET(DEVMODEW, dmICMMethod), dmW.dmSize); + for (i = dmW.dmSize; i < sizeof(DEVMODEW); ++i) + { + if (((BYTE *)&dmW)[i] != 0xcc) + break; + } + ok(i == sizeof(DEVMODEW), "data modified at offset %u.\n", i); + + memset(&dmW, 0xcc, sizeof(dmW)); + ret = EnumDisplaySettingsW(NULL, 0, &dmW); + ok(ret, "EnumDisplaySettingsW failed, error %#lx\n", GetLastError()); + ok(dmW.dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod), "Expect dmSize %lu, got %u\n", + FIELD_OFFSET(DEVMODEW, dmICMMethod), dmW.dmSize); + for (i = dmW.dmSize; i < sizeof(DEVMODEW); ++i) + { + if (((BYTE *)&dmW)[i] != 0xcc) + break; + } + ok(i == sizeof(DEVMODEW), "data modified at offset %u.\n", i); + + memset(&dm, 0xcc, sizeof(dm)); + ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm); + ok(ret, "EnumDisplaySettingsW failed, error %#lx\n", GetLastError()); + ok(dm.dmSize == FIELD_OFFSET(DEVMODEA, dmICMMethod), "Expect dmSize %lu, got %u\n", + FIELD_OFFSET(DEVMODEA, dmICMMethod), dm.dmSize); + ok((dm.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#lx, got %#lx\n", + setting_fields, dm.dmFields); + for (i = dm.dmSize; i < sizeof(DEVMODEA); ++i) + { + if (((BYTE *)&dm)[i] != 0xcc) + break; + } + ok(i == sizeof(DEVMODEA), "data modified at offset %u.\n", i); + memset(&dmW, 0, sizeof(dmW)); dmW.dmSize = sizeof(dmW); ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &dmW); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 6afb825e149..eee81497139 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -510,7 +510,7 @@ static BOOL read_source_mode( HKEY hkey, UINT index, DEVMODEW *mode ) else return FALSE; if (!query_reg_ascii_value( hkey, key, value, sizeof(value_buf) )) return FALSE; - memcpy( &mode->dmFields, value->Data, sizeof(*mode) - offsetof(DEVMODEW, dmFields) ); + memcpy( &mode->dmFields, value->Data, offsetof(DEVMODEW, dmICMMethod) - offsetof(DEVMODEW, dmFields) ); return TRUE; } @@ -554,7 +554,7 @@ static BOOL source_set_registry_settings( const struct source *source, const DEV static BOOL source_get_current_settings( const struct source *source, DEVMODEW *mode ) { - memcpy( &mode->dmFields, &source->current.dmFields, sizeof(*mode) - offsetof(DEVMODEW, dmFields) ); + memcpy( &mode->dmFields, &source->current.dmFields, offsetof(DEVMODEW, dmICMMethod) - offsetof(DEVMODEW, dmFields) ); if (source->depth) mode->dmBitsPerPel = source->depth; return TRUE; } @@ -4447,7 +4447,7 @@ static BOOL source_enum_display_settings( const struct source *source, UINT inde continue; if (!i--) { - memcpy( &devmode->dmFields, &source_mode->dmFields, devmode->dmSize - FIELD_OFFSET(DEVMODEW, dmFields) ); + memcpy( &devmode->dmFields, &source_mode->dmFields, offsetof(DEVMODEW, dmICMMethod) - FIELD_OFFSET(DEVMODEW, dmFields) ); devmode->dmDisplayFlags &= ~WINE_DM_UNSUPPORTED; return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9672
This fixes a regression in Distant Worlds 2 (which crashes on start) introduced between Wine 9 and 10. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9672#note_124632
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9672
participants (3)
-
Paul Gofman -
Paul Gofman (@gofman) -
Rémi Bernon