[PATCH 0/1] MR10314: vbscript: Convert string to number for comparison operators.
When one operand was a string and the other numeric, VBScript should have converted the string to a double before comparing. VarCmp did not do this automatically, resulting in incorrect string comparison. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56281 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10314
From: Francis De Brabandere <francisdb@gmail.com> When one operand was a string and the other numeric, VBScript should have converted the string to a double before comparing. VarCmp did not do this automatically, resulting in incorrect string comparison. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56281 --- dlls/vbscript/interp.c | 23 ++++++++++++++++++++++- dlls/vbscript/tests/lang.vbs | 13 +++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 127fcc2c05e..5ba3988ec4e 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -1941,11 +1941,32 @@ static HRESULT interp_imp(exec_ctx_t *ctx) return stack_push(ctx, &v); } +static inline BOOL is_numeric_vt(VARTYPE vt) +{ + return vt == VT_I2 || vt == VT_I4 || vt == VT_R4 || vt == VT_R8 + || vt == VT_CY || vt == VT_DATE || vt == VT_BOOL || vt == VT_UI1; +} + static HRESULT var_cmp(exec_ctx_t *ctx, VARIANT *l, VARIANT *r) { + VARIANT v; + HRESULT hres; + TRACE("%s %s\n", debugstr_variant(l), debugstr_variant(r)); - /* FIXME: Fix comparing string to number */ + /* VBScript compares string to number by converting the string to double, + * while VarCmp would use string comparison. */ + if(V_VT(l) == VT_BSTR && is_numeric_vt(V_VT(r))) { + V_VT(&v) = VT_EMPTY; + hres = VariantChangeType(&v, l, 0, VT_R8); + if(SUCCEEDED(hres)) + return VarCmp(&v, r, ctx->script->lcid, 0); + }else if(V_VT(r) == VT_BSTR && is_numeric_vt(V_VT(l))) { + V_VT(&v) = VT_EMPTY; + hres = VariantChangeType(&v, r, 0, VT_R8); + if(SUCCEEDED(hres)) + return VarCmp(l, &v, ctx->script->lcid, 0); + } return VarCmp(l, r, ctx->script->lcid, 0); } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 0025bfeddcf..e0db657149e 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -2289,4 +2289,17 @@ f1 not 1 = 0 arr (0) = 2 xor -2 +' String-to-number comparison: string operand must be converted to number +Dim sNum +sNum = "0" +Call ok(not (sNum > 30), """0"" > 30 should be false") +Call ok(sNum < 30, """0"" < 30 should be true") +Call ok(not ("0" > 30), """0"" > 30 literal should be false") +Call ok("0" < 30, """0"" < 30 literal should be true") +Call ok("10" > 9, """10"" > 9 should be true") +Call ok(not ("10" > 100), """10"" > 100 should be false") +Call ok("10" < 100, """10"" < 100 should be true") +Call ok("42" = 42, """42"" = 42 should be true") +Call ok(not ("42" = 43), """42"" = 43 should be false") + reportSuccess() -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10314
Maybe we should be fixing VarCmp() instead. Also tests don't cover floats. It should probably use float->str conversion for such tests. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10314#note_132038
@nsivov I'm coming to this from the vbscript side (running vbs pinball table sim scripts), I have no idea how the rest of the windows api is supposed to handle this. I'm willing to move this higher up, are there tests on windows that will check both wine and win behave the same? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10314#note_132039
On Thu Mar 12 15:19:53 2026 +0000, Nikolay Sivov wrote:
Maybe we should be fixing VarCmp() instead. Also tests don't cover floats. It should probably use float->str conversion for such tests. Not convinced this should be pushed down to `VarCmp`. I expect the OLE api to be more tested / covered / used than the vbscript dll?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10314#note_132046
participants (3)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb) -
Nikolay Sivov (@nsivov)