From 9185cdcc795b50dcea48c7ff7b6f51d4359e5628 Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 24 Feb 2020 20:48:51 +0000 Subject: [PATCH] [Kernel] Fix wide-printf functions not processing %ws format correctly This would break format strings like memory://%.*ws (that dashboard tries using), because the "ws" part would set FF_IsWide, but FF_IsWide actually seemed to be used as an "is opposite encoding" flag. Since the format string is wide that'd make it treat the param as ASCII, but in dashboards case the param string provided is actually a wide string. (in other words, it seems %ws is supposed to mean that the param is always a wide string, not that the param is just opposite encoding) This changes the old FF_IsWide to FF_InvertWide, and adds a new FF_IsWide that means that the param is always wide. --- src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc index 71fa6046b..88b59c74e 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc @@ -49,6 +49,7 @@ enum FormatFlags { FF_IsWide = 1 << 9, FF_IsSigned = 1 << 10, FF_ForceLeadingZero = 1 << 11, + FF_InvertWide = 1 << 12, }; enum ArgumentSize { @@ -316,16 +317,14 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args, // wide character switch (c) { case 'C': { - if (!(flags & (FF_IsShort | FF_IsLong | FF_IsWide))) { - flags |= FF_IsWide; - } + flags |= FF_InvertWide; // fall through } // character case 'c': { bool is_wide; - if (flags & FF_IsLong) { + if (flags & (FF_IsLong | FF_IsWide)) { // "An lc, lC, wc or wC type specifier is synonymous with C in // printf functions and with c in wprintf functions." is_wide = true; @@ -334,7 +333,7 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args, // functions and with C in wprintf functions." is_wide = false; } else { - is_wide = ((flags & FF_IsWide) != 0) ^ wide; + is_wide = ((flags & FF_InvertWide) != 0) ^ wide; } auto value = args.get32(); @@ -521,9 +520,7 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args, // wide string case 'S': { - if (!(flags & (FF_IsShort | FF_IsLong | FF_IsWide))) { - flags |= FF_IsWide; - } + flags |= FF_InvertWide; // fall through } @@ -540,7 +537,7 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args, } else { void* str = SHIM_MEM_ADDR(pointer); bool is_wide; - if (flags & FF_IsLong) { + if (flags & (FF_IsLong | FF_IsWide)) { // "An ls, lS, ws or wS type specifier is synonymous with S in // printf functions and with s in wprintf functions." is_wide = true; @@ -549,7 +546,7 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args, // functions and with S in wprintf functions." is_wide = false; } else { - is_wide = ((flags & (FF_IsWide)) != 0) ^ wide; + is_wide = ((flags & FF_InvertWide) != 0) ^ wide; } int32_t length;