[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] hvm: Fix undefined bit shifting in mmio emulation path
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1175010980 -3600 # Node ID d4ddaff75afd0231e5d832d591196b32f8a7ecc7 # Parent 681ed46676a6a6988fa1d0c2e550af65673fb82c hvm: Fix undefined bit shifting in mmio emulation path In functions set_eflags_* (xen/arch/x86/hvm/io.c), if the first argument "size" equals sizeof(long), the following code will produce unintended and invalid result: unsigned long mask = (1 << (8 * size)) - 1; In ANSI C, if the shift amount is greater or equal to the width of the data type, the result is undefined. Specifically on x86, a bit mask is applied to the shift amount, so that more significant bits are ignored. So the above expression results 0x0 instead of the intended ~0UL. This patch fixes this issue. Because size=0 is not a valid parameter, rewriting the code using right shift avoids an additional condition check. Signed-off-by: Qing He <qing.he@xxxxxxxxx> --- xen/arch/x86/hvm/io.c | 28 ++++++++++++++++++++++++---- 1 files changed, 24 insertions(+), 4 deletions(-) diff -r 681ed46676a6 -r d4ddaff75afd xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Tue Mar 27 16:45:37 2007 +0100 +++ b/xen/arch/x86/hvm/io.c Tue Mar 27 16:56:20 2007 +0100 @@ -292,7 +292,11 @@ static inline void set_eflags_CF(int siz static inline void set_eflags_CF(int size, unsigned long v1, unsigned long v2, struct cpu_user_regs *regs) { - unsigned long mask = (1 << (8 * size)) - 1; + unsigned long mask; + + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); if ((v1 & mask) > (v2 & mask)) regs->eflags |= X86_EFLAGS_CF; @@ -303,7 +307,13 @@ static inline void set_eflags_OF(int siz static inline void set_eflags_OF(int size, unsigned long v1, unsigned long v2, unsigned long v3, struct cpu_user_regs *regs) { - if ((v3 ^ v2) & (v3 ^ v1) & (1 << ((8 * size) - 1))) + unsigned long mask; + + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); + + if ((v3 ^ v2) & (v3 ^ v1) & mask) regs->eflags |= X86_EFLAGS_OF; } @@ -317,7 +327,11 @@ static inline void set_eflags_ZF(int siz static inline void set_eflags_ZF(int size, unsigned long v1, struct cpu_user_regs *regs) { - unsigned long mask = (1 << (8 * size)) - 1; + unsigned long mask; + + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); if ((v1 & mask) == 0) regs->eflags |= X86_EFLAGS_ZF; @@ -326,7 +340,13 @@ static inline void set_eflags_SF(int siz static inline void set_eflags_SF(int size, unsigned long v1, struct cpu_user_regs *regs) { - if (v1 & (1 << ((8 * size) - 1))) + unsigned long mask; + + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); + + if (v1 & mask) regs->eflags |= X86_EFLAGS_SF; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |