Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*++
Copyright (c) Microsoft Corporation
Module Name:
rtloverflow.c
Abstract:
32bit/64bit signed/unsigned add/multiply with overflow checking
Author:
Jay Krell (JayKrell) January 2002
Revision History:
Environment:
anywhere, only dependency is STATUS_SUCCESS, STATUS_INTEGER_OVERFLOW Initial client is win32k.sys font loading "rewrite".
--*/
#include "ntos.h"
#include "nt.h"
#include "ntstatus.h"
#include "ntrtloverflow.h"
//
// add functions are FORCEINLINE in ntrtl.h
//
NTSTATUS RtlpAddWithOverflowCheckUnsigned64( unsigned __int64 *pc, unsigned __int64 a, unsigned __int64 b ) { return RtlUnsignedAddWithCarryOut64(pc, a, b) ? STATUS_INTEGER_OVERFLOW : STATUS_SUCCESS; }
NTSTATUS NTAPI RtlMultiplyWithOverflowCheckSigned32( __int32 * pc, __int32 a, __int32 b ) { __int64 c;
c = ((__int64)a) * ((__int64)b); *pc = (__int32)c; c &= 0xFFFFFFFF80000000ui64; if ((a < 0) != (b < 0)) { return (c == 0xFFFFFFFF80000000ui64) ? STATUS_SUCCESS : STATUS_INTEGER_OVERFLOW; } else { return (c == 0) ? STATUS_SUCCESS : STATUS_INTEGER_OVERFLOW; } }
NTSTATUS NTAPI RtlMultiplyWithOverflowCheckUnsigned32( unsigned __int32 * pc, unsigned __int32 a, unsigned __int32 b ) { unsigned __int64 c;
c = ((unsigned __int64)a) * ((unsigned __int64)b); *pc = (unsigned __int32)c; c &= 0xFFFFFFFF00000000ui64; return (c == 0) ? STATUS_SUCCESS : STATUS_INTEGER_OVERFLOW; }
NTSTATUS NTAPI RtlMultiplyWithOverflowCheckUnsigned64( unsigned __int64 * pc, unsigned __int64 a, unsigned __int64 b ) { unsigned __int64 ah; unsigned __int64 al; unsigned __int64 bh; unsigned __int64 bl; unsigned __int64 c; unsigned __int64 m; NTSTATUS Status;
ah = (a >> 32); bh = (b >> 32);
//
// 09 * 09 = 81 => no overflow
//
if (ah == 0 && bh == 0) { *pc = (a * b); Status = STATUS_SUCCESS; goto Exit; }
//
// 10 * 10 = 100 => overflow
//
if (bh != 0 && ah != 0) { Status = STATUS_INTEGER_OVERFLOW; goto Exit; }
al = (a & 0xFFFFFFFFui64); bl = (b & 0xFFFFFFFFui64);
//
// a * b = al * bl + (al * bh) * "10" + (ah * bl) * "10" + (ah * bh) * "100"
//
c = (al * bl); m = (ah * bl); if ((m & 0xFFFFFFFF00000000ui64) != 0) { //
// for example: 90 * 09 => overflow
// 09 * 09 => 81, 8 != 0 => overflow
//
// ah != 0 or bh != 0 very often but not always leads to overflow
// 40 * 2 is ok, but 40 * 3 and 50 * 2 are not
//
Status = STATUS_INTEGER_OVERFLOW; goto Exit; } if (!NT_SUCCESS(Status = RtlpAddWithOverflowCheckUnsigned64(&c, c, m << 32))) { goto Exit; } m = (al * bh); if ((m & 0xFFFFFFFF00000000ui64) != 0) { //
// for example: 09 * 90 => overflow
// 09 * 09 => 81, 8 != 0 => overflow
//
// ah != 0 or bh != 0 very often but not always leads to overflow
// 40 * 2 is ok, but 40 * 3 and 50 * 2 are not
//
Status = STATUS_INTEGER_OVERFLOW; goto Exit; } if (!NT_SUCCESS(Status = RtlpAddWithOverflowCheckUnsigned64(&c, c, m << 32))) { goto Exit; } *pc = c; Status = STATUS_SUCCESS; Exit: return Status; }
|