From 50c57625fe8b13afcfd7c694a2a0717a0788f4da Mon Sep 17 00:00:00 2001 From: edleno2 Date: Wed, 19 May 2021 15:22:47 -0700 Subject: [PATCH 01/14] Fixes for unit test failures for System.Convert Removed call to GetIntegerPart since it couldn't support UInt64 conversions and edit for invalid values. Wrote new string parse loop based on code that is being used for SUPPORT_ANY_BASE_CONVERSION. Moved some code so it could be used by both SUPPORT_ANY... and the radix 10/16 logic. Possible problem change in Double parsing - used pow() method to better generate the IEEE 574 compliant double in storage. pow() is considered to be slow, but without a more precise float multiplication the resulting double will not match what is used by the Roslyn compiler when creating and comparing doubles. Fixes #715 --- .../CorLib/corlib_native_System_Convert.cpp | 122 ++++++++++++------ src/CLR/Helpers/nanoprintf/nanoprintf.c | 10 ++ 2 files changed, 95 insertions(+), 37 deletions(-) diff --git a/src/CLR/CorLib/corlib_native_System_Convert.cpp b/src/CLR/CorLib/corlib_native_System_Convert.cpp index 50090e6c7d..41c95de62a 100644 --- a/src/CLR/CorLib/corlib_native_System_Convert.cpp +++ b/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -16,26 +16,29 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING char* str = (char*)stack.Arg0().RecoverString(); signed int radix = stack.Arg4().NumericByRef().s4; - -#if (SUPPORT_ANY_BASE_CONVERSION == TRUE) - // suport for conversion from any base - char* endptr = NULL; - bool isUInt64 = false; bool isSigned = (bool)stack.Arg1().NumericByRef().u1; long long minValue = stack.Arg2().NumericByRef().s8; long long maxValue = stack.Arg3().NumericByRef().s8; - - // UInt64? => use also strtoull the result will be casted to Int64 - if (minValue == 0 && maxValue == 0) { + if (minValue == 0 && maxValue == 0) + { isUInt64 = true; isSigned = false; + } + //allow spaces before digits + while (*str == ' ') + { + str++; + } + char* endptr = NULL; - //allow spaces before digits - while (*str == ' ') { - str++; - } +#if (SUPPORT_ANY_BASE_CONVERSION == TRUE) + // suport for conversion from any base + + + // UInt64? => use also strtoull the result will be casted to Int64 + if (isUint64) //UInt64 can't begin with minus if (*str == '-' ) { @@ -86,30 +89,75 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING NANOCLR_NOCLEANUP(); #else // support for conversion from base 10 and 16 (partial) - if(radix == 10) { // conversion from base 10 - + bool negReturnExpected = false; // check for minus sign - if(*str == '-') + if (*str == '-') { - // call GetIntegerPart() in 'guess' mode by throwing a crazy number for the length - result = GetIntegerPart((str + 1), 99); - - // is negative - result *= -1; + if (isSigned == false) + { + // Can not use negative string with unsigned interface. This exception is just fail safe - the + // callers of this native method are checking and throwing a better formatted exception + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + negReturnExpected = true; + str++; } - // check for plus sign - else if(*str == '+') + else if (*str == '+') { - // call GetIntegerPart() in 'guess' mode by throwing a crazy number for the length - result = GetIntegerPart((str + 1), 99); + str++; + } + uint64_t intPart = 0; + uint64_t lastValue = 0; + for (int i = 0; i < 99; i++) // guess at no more than 99 characters + { + if (*str < '0' + || *str > '9') + { + endptr = str; + // allow spaces after digits + while (*endptr == ' ') + { + endptr++; + } + // should reach end of string no aditional chars + if (*endptr == 0) + { + break; + } + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); // non-numeric (and not trailing space) + } + intPart = (intPart * 10) + (*str - '0'); // advance the digits and add the current number + if (intPart < lastValue) // the above operation overflowed the value + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + lastValue = intPart; + str++; + if (*str == '\0') + { + break; + } + } + // intPart now holds a positive number from the string. + result = (int64_t)intPart; // this MAY have made the result negative by overflowing the buffer - which we do for uint64 logic + if (negReturnExpected) + { + result *= -1; + if (result < minValue) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } } else { - // call GetIntegerPart() in 'guess' mode by throwing a crazy number for the length - result = GetIntegerPart(str, 99); + if (isUInt64 == false // result will be negative for large uints, and we checked for overflow above + && result > maxValue) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } } } @@ -117,6 +165,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING { // conversion from base 16 result = GetIntegerFromHexString(str); + //??? check against min/max? Signed possible? } else { @@ -125,8 +174,10 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } stack.SetResult_I8(result); + NANOCLR_NOCLEANUP(); } - NANOCLR_NOCLEANUP_NOLABEL(); + + //NANOCLR_NOCLEANUP_NOLABEL(); #endif // defined(SUPPORT_ANY_BASE_CONVERSION) } @@ -300,17 +351,14 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN if (hasMinusExponentialSign || hasPlusExponentialSign) exponentialSign++; // get the exponential part int exponent = GetIntegerPart((str+exponentialSign+1), (length-exponentialSign-1)); - // each time multiply or divide by 10 - for (int i = 0; i < exponent; i++) + double outExponent = pow(10, exponent); + if (hasMinusExponentialSign) { - if (hasMinusExponentialSign) - { - returnValue /= 10; - } - else - { - returnValue *= 10; - } + returnValue = returnValue / outExponent; + } + else + { + returnValue = returnValue * outExponent; } } diff --git a/src/CLR/Helpers/nanoprintf/nanoprintf.c b/src/CLR/Helpers/nanoprintf/nanoprintf.c index 4bf453a52d..757b6a44a9 100644 --- a/src/CLR/Helpers/nanoprintf/nanoprintf.c +++ b/src/CLR/Helpers/nanoprintf/nanoprintf.c @@ -3,6 +3,16 @@ // Portions Copyright (c) 2001, 2002 Georges Menie. All rights reserved. // Portions Copyright (c) 2009-2013 Daniel D Miller. All rights reserved. // See LICENSE file in the project root for full license information. +// +// Notes on this implementation: This is a small/fast implementation of printf variants +// for double (floating) numbers. It is a compromise of size and speed over capability. +// In general the algorithm used in this code can only format a small range of the possible +// values that can be fit in a double. A double can hold roughly +/-1e308, but the code in +// this program uses shifting of 64 bits, so a range of roughly +/-1e18 (2^63). The method +// npf_dsplit_abs supports this limitation and will return a value of "oor" (out-of-range) +// for numbers over 2^63. It will return zero for any numbers below 2^-63. +// +// See the information here: http://0x80.pl/notesen/2015-12-29-float-to-string.html // /* From c5746970e1cfde1b790e302340eb845579fb18b2 Mon Sep 17 00:00:00 2001 From: edleno2 Date: Sun, 23 May 2021 19:53:42 -0700 Subject: [PATCH 02/14] Fixes for failing units tests Cleaned up brackets in system convert to be consistent with rest of file. Added "signed" to char for cast operation - win32 treats char as signed, but gcc does not. Adding signed makes this un-ambiguous. Fix #715 --- .../CorLib/corlib_native_System_Convert.cpp | 29 ++++++++++++------- src/CLR/Helpers/nanoprintf/nanoprintf.c | 2 +- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/CLR/CorLib/corlib_native_System_Convert.cpp b/src/CLR/CorLib/corlib_native_System_Convert.cpp index 41c95de62a..38b4e12149 100644 --- a/src/CLR/CorLib/corlib_native_System_Convert.cpp +++ b/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -38,10 +38,12 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING // UInt64? => use also strtoull the result will be casted to Int64 - if (isUint64) + if (isUInt64) + { //UInt64 can't begin with minus - if (*str == '-' ) { + if (*str == '-' ) + { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); } } @@ -57,32 +59,39 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING // It is necessary to add a check // if no valid conversion endptr is equal str - if (str == endptr) { + if (str == endptr) + { NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); } // allow spaces after digits - while (*endptr == ' ') { + while (*endptr == ' ') + { endptr++; } // should reach end of string no aditional chars - if (*endptr != 0) { + if (*endptr != 0) + { NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); } // the signed values for SByte, Int16 and Int32 are always positive for base 2, 8 or 16 conversions // because the 64-bit function strtoll is used; need the post process the value // if the result is greater max and smaller (max + 1) * 2 this value should be subtracted - if (radix == 2 || radix == 8 || radix == 16) { + if (radix == 2 || radix == 8 || radix == 16) + { if (isSigned && result > maxValue && result < (maxValue + 1) * 2) result -= (maxValue + 1) * 2; } - if (!isUInt64 && !isSigned && (uint64_t)result > (uint64_t)maxValue) { - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); - } else if (!isUInt64 && (result > maxValue || result < minValue)) { + if (!isUInt64 && !isSigned && (uint64_t)result > (uint64_t)maxValue) + { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); - } else { + } else if (!isUInt64 && (result > maxValue || result < minValue)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } else + { stack.SetResult_I8(result); } } diff --git a/src/CLR/Helpers/nanoprintf/nanoprintf.c b/src/CLR/Helpers/nanoprintf/nanoprintf.c index 757b6a44a9..e86ce0cee7 100644 --- a/src/CLR/Helpers/nanoprintf/nanoprintf.c +++ b/src/CLR/Helpers/nanoprintf/nanoprintf.c @@ -651,7 +651,7 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) NPF_EXTRACT(SHORT, short, int); NPF_EXTRACT(LONG, long, long); NPF_EXTRACT(LONG_DOUBLE, int, int); - NPF_EXTRACT(CHAR, char, int); + NPF_EXTRACT(CHAR, signed char, int); #if NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS == 1 NPF_EXTRACT(LARGE_LONG_LONG, long long, long long); NPF_EXTRACT(LARGE_INTMAX, intmax_t, intmax_t); From faaf7b770c959f53909c7a29fa764d918f4c6a66 Mon Sep 17 00:00:00 2001 From: nfbot Date: Mon, 24 May 2021 03:14:37 +0000 Subject: [PATCH 03/14] Code style fixes Automated fixes for code style. --- .../CorLib/corlib_native_System_Convert.cpp | 272 +++++++++--------- src/CLR/Helpers/nanoprintf/nanoprintf.c | 10 +- 2 files changed, 146 insertions(+), 136 deletions(-) diff --git a/src/CLR/CorLib/corlib_native_System_Convert.cpp b/src/CLR/CorLib/corlib_native_System_Convert.cpp index 38b4e12149..36802757dd 100644 --- a/src/CLR/CorLib/corlib_native_System_Convert.cpp +++ b/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -8,13 +8,14 @@ #include #include -HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4( CLR_RT_StackFrame& stack ) +HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4( + CLR_RT_StackFrame &stack) { NANOCLR_HEADER(); { int64_t result = 0; - char* str = (char*)stack.Arg0().RecoverString(); + char *str = (char *)stack.Arg0().RecoverString(); signed int radix = stack.Arg4().NumericByRef().s4; bool isUInt64 = false; @@ -26,71 +27,73 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING isUInt64 = true; isSigned = false; } - //allow spaces before digits - while (*str == ' ') + // allow spaces before digits + while (*str == ' ') { str++; } - char* endptr = NULL; + char *endptr = NULL; #if (SUPPORT_ANY_BASE_CONVERSION == TRUE) // suport for conversion from any base - // UInt64? => use also strtoull the result will be casted to Int64 if (isUInt64) { - //UInt64 can't begin with minus - if (*str == '-' ) + // UInt64 can't begin with minus + if (*str == '-') { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); } } // convert via strtoll / strtoull - result = isSigned ? strtoll(str, &endptr, radix) : (long long) strtoull(str, &endptr, radix); + result = isSigned ? strtoll(str, &endptr, radix) : (long long)strtoull(str, &endptr, radix); - // TODO: + // TODO: // If the value in input string is out of the range of representable values - // by a long long int / unsigned long int, the function returns - // LLONG_MAX or LLONG_MIN for signed conversion + // by a long long int / unsigned long int, the function returns + // LLONG_MAX or LLONG_MIN for signed conversion // and ULONG_MAX for unsigned conversion // It is necessary to add a check // if no valid conversion endptr is equal str - if (str == endptr) + if (str == endptr) { NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); } // allow spaces after digits - while (*endptr == ' ') + while (*endptr == ' ') { endptr++; } // should reach end of string no aditional chars - if (*endptr != 0) + if (*endptr != 0) { NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); } - + // the signed values for SByte, Int16 and Int32 are always positive for base 2, 8 or 16 conversions // because the 64-bit function strtoll is used; need the post process the value // if the result is greater max and smaller (max + 1) * 2 this value should be subtracted - if (radix == 2 || radix == 8 || radix == 16) + if (radix == 2 || radix == 8 || radix == 16) { - if (isSigned && result > maxValue && result < (maxValue + 1) * 2) result -= (maxValue + 1) * 2; + if (isSigned && result > maxValue && result < (maxValue + 1) * 2) + result -= (maxValue + 1) * 2; } - if (!isUInt64 && !isSigned && (uint64_t)result > (uint64_t)maxValue) + if (!isUInt64 && !isSigned && (uint64_t)result > (uint64_t)maxValue) { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); - } else if (!isUInt64 && (result > maxValue || result < minValue)) + } + else if (!isUInt64 && (result > maxValue || result < minValue)) { - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); - } else + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + else { stack.SetResult_I8(result); } @@ -98,7 +101,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING NANOCLR_NOCLEANUP(); #else // support for conversion from base 10 and 16 (partial) - if(radix == 10) + if (radix == 10) { // conversion from base 10 bool negReturnExpected = false; @@ -120,10 +123,9 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } uint64_t intPart = 0; uint64_t lastValue = 0; - for (int i = 0; i < 99; i++) // guess at no more than 99 characters + for (int i = 0; i < 99; i++) // guess at no more than 99 characters { - if (*str < '0' - || *str > '9') + if (*str < '0' || *str > '9') { endptr = str; // allow spaces after digits @@ -136,10 +138,10 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING { break; } - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); // non-numeric (and not trailing space) + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); // non-numeric (and not trailing space) } - intPart = (intPart * 10) + (*str - '0'); // advance the digits and add the current number - if (intPart < lastValue) // the above operation overflowed the value + intPart = (intPart * 10) + (*str - '0'); // advance the digits and add the current number + if (intPart < lastValue) // the above operation overflowed the value { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); } @@ -150,11 +152,12 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING break; } } - // intPart now holds a positive number from the string. - result = (int64_t)intPart; // this MAY have made the result negative by overflowing the buffer - which we do for uint64 logic + // intPart now holds a positive number from the string. + result = (int64_t)intPart; // this MAY have made the result negative by overflowing the buffer - which we do + // for uint64 logic if (negReturnExpected) { - result *= -1; + result *= -1; if (result < minValue) { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); @@ -162,19 +165,18 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } else { - if (isUInt64 == false // result will be negative for large uints, and we checked for overflow above + if (isUInt64 == false // result will be negative for large uints, and we checked for overflow above && result > maxValue) { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); } } - } - else if(radix == 16) + else if (radix == 16) { // conversion from base 16 result = GetIntegerFromHexString(str); - //??? check against min/max? Signed possible? + //??? check against min/max? Signed possible? } else { @@ -186,25 +188,24 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING NANOCLR_NOCLEANUP(); } - //NANOCLR_NOCLEANUP_NOLABEL(); + // NANOCLR_NOCLEANUP_NOLABEL(); #endif // defined(SUPPORT_ANY_BASE_CONVERSION) - } -HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRING( CLR_RT_StackFrame& stack ) +HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRING(CLR_RT_StackFrame &stack) { NANOCLR_HEADER(); { - char* str = (char*)stack.Arg0().RecoverString(); + char *str = (char *)stack.Arg0().RecoverString(); - #if (SUPPORT_ANY_BASE_CONVERSION == TRUE) +#if (SUPPORT_ANY_BASE_CONVERSION == TRUE) // suport for conversion from any base - stack.SetResult_R8 (strtod(str, nullptr)); + stack.SetResult_R8(strtod(str, nullptr)); } NANOCLR_NOCLEANUP_NOLABEL(); - #else +#else // support for conversion from base 10 and 16 (partial) // in this particular function the base isn't relevant @@ -218,7 +219,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN double returnValue = 0.0; // first pass, get count of decimal places, integer part and check for valid chars - char* temp = str; + char *temp = str; while (*temp != '\0') { switch (*temp) @@ -230,7 +231,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN { hasMinusSign = true; } - else + else { // found a minus signal NOT at the start of the string NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); @@ -242,7 +243,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN { hasMinusExponentialSign = true; } - else + else { // found a minus signal NOT at the start of the exponent NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); @@ -257,7 +258,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN { hasPlusSign = true; } - else + else { // found a plus signal NOT at the start of the string NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); @@ -269,7 +270,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN { hasPlusExponentialSign = true; } - else + else { // found a plus signal NOT at the start of the exponent NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); @@ -323,22 +324,25 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN else if (decimalPoint == 0) { // string starts with the decimal point, only has fractional part - returnValue = GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1)); + returnValue = GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); } else if (hasMinusSign || hasPlusSign) { // string starts with sign and... - - if(decimalPoint == 1) + + if (decimalPoint == 1) { // ... is followed by a decimal point, only has fractional part - returnValue = GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1)); + returnValue = + GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); } else { // ... has integer and fractional parts - returnValue = GetIntegerPart(str+1, decimalPoint-1); - returnValue = (returnValue + GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1))); + returnValue = GetIntegerPart(str + 1, decimalPoint - 1); + returnValue = + (returnValue + + GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1))); } if (hasMinusSign) @@ -350,94 +354,95 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN { // string has integer and fractional parts returnValue = GetIntegerPart(str, decimalPoint); - returnValue = returnValue + GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1)); + returnValue = returnValue + + GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); } // exponential part found? if (exponentialSign != -1) { // advance by one if a sign (+ or -) is after the exponential sign - if (hasMinusExponentialSign || hasPlusExponentialSign) exponentialSign++; + if (hasMinusExponentialSign || hasPlusExponentialSign) + exponentialSign++; // get the exponential part - int exponent = GetIntegerPart((str+exponentialSign+1), (length-exponentialSign-1)); + int exponent = GetIntegerPart((str + exponentialSign + 1), (length - exponentialSign - 1)); double outExponent = pow(10, exponent); - if (hasMinusExponentialSign) + if (hasMinusExponentialSign) { - returnValue = returnValue / outExponent; + returnValue = returnValue / outExponent; } else { - returnValue = returnValue * outExponent; + returnValue = returnValue * outExponent; } } stack.SetResult_R8(returnValue); - } + } NANOCLR_NOCLEANUP(); - #endif // defined(SUPPORT_ANY_BASE_CONVERSION) - +#endif // defined(SUPPORT_ANY_BASE_CONVERSION) } -HRESULT Library_corlib_native_System_Convert::ToBase64String___STATIC__STRING__SZARRAY_U1__I4__I4__BOOLEAN( CLR_RT_StackFrame& stack ) +HRESULT Library_corlib_native_System_Convert::ToBase64String___STATIC__STRING__SZARRAY_U1__I4__I4__BOOLEAN( + CLR_RT_StackFrame &stack) { NANOCLR_HEADER(); size_t outputLength; - char* outArray = NULL; - char* outArrayWitLineBreak = NULL; - uint8_t* inArrayPointer = NULL; + char *outArray = NULL; + char *outArrayWitLineBreak = NULL; + uint8_t *inArrayPointer = NULL; uint8_t lineBreakCount; uint16_t offsetIndex = 0; uint8_t count = 0; uint16_t result; - CLR_RT_HeapBlock_Array* inArray = stack.Arg0().DereferenceArray(); + CLR_RT_HeapBlock_Array *inArray = stack.Arg0().DereferenceArray(); size_t offset = (size_t)stack.Arg1().NumericByRef().s4; size_t length = (size_t)stack.Arg2().NumericByRef().s4; bool insertLineBreaks = (bool)stack.Arg3().NumericByRefConst().u1; - if(inArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); + if (inArray == NULL) + NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); - inArrayPointer = (uint8_t*)inArray->GetFirstElement(); + inArrayPointer = (uint8_t *)inArray->GetFirstElement(); inArrayPointer += (offset * sizeof(uint8_t)); // compute base64 string length outputLength = 4 * ((length + 2) / 3); // need malloc with base64 string length plus string terminator (+1) - outArray = (char*)platform_malloc(outputLength + 1); + outArray = (char *)platform_malloc(outputLength + 1); // check if have allocation - if (outArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + if (outArray == NULL) + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); // perform the operation // need to tweak the parameter with the output length because it includes room for the terminator - result = mbedtls_base64_encode( - (unsigned char*)outArray, - (outputLength + 1), - &outputLength, - inArrayPointer, - length ); - - if(result != 0) + result = + mbedtls_base64_encode((unsigned char *)outArray, (outputLength + 1), &outputLength, inArrayPointer, length); + + if (result != 0) { // internal error occurred NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); } - if(insertLineBreaks) + if (insertLineBreaks) { // get line break count (line break every 76 chars) lineBreakCount = outputLength / 76; - // need malloc with base64 string length plus line breaks (line break is 2 char long: CR + LF) plus final line break - outArrayWitLineBreak = (char*)platform_malloc(outputLength + (lineBreakCount * 2) + 2); + // need malloc with base64 string length plus line breaks (line break is 2 char long: CR + LF) plus final line + // break + outArrayWitLineBreak = (char *)platform_malloc(outputLength + (lineBreakCount * 2) + 2); - for(int i = 0; i <= lineBreakCount; i++) + for (int i = 0; i <= lineBreakCount; i++) { // how many chars to copy - if(outputLength > 76) + if (outputLength > 76) { // first/next 76 chars count = 76; @@ -453,7 +458,7 @@ HRESULT Library_corlib_native_System_Convert::ToBase64String___STATIC__STRING__S memcpy(outArrayWitLineBreak + offsetIndex, outArray + (offsetIndex - (i * 2)), count); // remove copied chars from original output length if more than 76 chars still to be copied - if(outputLength >= 76) + if (outputLength >= 76) { // more chars @@ -475,57 +480,61 @@ HRESULT Library_corlib_native_System_Convert::ToBase64String___STATIC__STRING__S outArrayWitLineBreak[offsetIndex] = 0; } } - // set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + // set a return result in the stack argument using the appropriate SetResult according to the variable type (a + // string here) NANOCLR_CHECK_HRESULT(stack.SetResult_String(outArrayWitLineBreak)); } else { - // set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + // set a return result in the stack argument using the appropriate SetResult according to the variable type (a + // string here) NANOCLR_CHECK_HRESULT(stack.SetResult_String(outArray)); } // need to free memory from arrays - platform_free((void*)outArray); + platform_free((void *)outArray); - if(outArrayWitLineBreak != NULL) + if (outArrayWitLineBreak != NULL) { - platform_free((void*)outArrayWitLineBreak); + platform_free((void *)outArrayWitLineBreak); } NANOCLR_NOCLEANUP(); } -HRESULT Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZARRAY_U1__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +HRESULT Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZARRAY_U1__SZARRAY_CHAR__I4( + CLR_RT_StackFrame &stack) { NANOCLR_HEADER(); size_t outputLength; - char* outArray = NULL; - uint16_t* inArrayPointerTmp = NULL; - uint8_t* inArrayPointer = NULL; + char *outArray = NULL; + uint16_t *inArrayPointerTmp = NULL; + uint8_t *inArrayPointer = NULL; uint8_t charValue; - CLR_UINT8* returnArray; + CLR_UINT8 *returnArray; int16_t i = 0; uint16_t result; - CLR_RT_HeapBlock_Array* inArray = stack.Arg0().DereferenceArray(); + CLR_RT_HeapBlock_Array *inArray = stack.Arg0().DereferenceArray(); size_t length = (size_t)stack.Arg1().NumericByRef().s4; - if(inArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); + if (inArray == NULL) + NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); outputLength = length / 4 * 3; // transform the 16 bits inArray to a 8 bits array so mbed knows how to convert it - inArrayPointerTmp = (uint16_t*)inArray->GetFirstElementUInt16(); - inArrayPointer = (uint8_t*)inArray->GetFirstElement(); - for(i = 0; i < (int16_t)length; i++) + inArrayPointerTmp = (uint16_t *)inArray->GetFirstElementUInt16(); + inArrayPointer = (uint8_t *)inArray->GetFirstElement(); + for (i = 0; i < (int16_t)length; i++) { *inArrayPointer = *inArrayPointerTmp; inArrayPointer++; inArrayPointerTmp++; } - - // pointer is pointing to the end + + // pointer is pointing to the end // point to last char in array and get it inArrayPointer--; charValue = *inArrayPointer; @@ -539,7 +548,7 @@ HRESULT Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZAR inArrayPointer--; charValue = *inArrayPointer; // adjust output length - if (charValue == '=') + if (charValue == '=') { outputLength--; } @@ -547,27 +556,28 @@ HRESULT Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZAR // reset pointer position (-2 because above we already went back two positions) inArrayPointer -= length - 2; - outArray = (char*)platform_malloc(outputLength + 1); + outArray = (char *)platform_malloc(outputLength + 1); // check malloc success - if (outArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + if (outArray == NULL) + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); // perform the operation // need to tweak the parameter with the output length because it includes room for the terminator - result = mbedtls_base64_decode( - (unsigned char*)outArray, - (outputLength + 1), - &outputLength, - inArrayPointer, - length ); - - if(result != 0) + result = + mbedtls_base64_decode((unsigned char *)outArray, (outputLength + 1), &outputLength, inArrayPointer, length); + + if (result != 0) { // internal error occurred NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); } - // create heap block array instance with appropriate size (the length of the output array) and type (byte which is uint8_t) - NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( stack.PushValueAndClear() , outputLength, g_CLR_RT_WellKnownTypes.m_UInt8 )); + // create heap block array instance with appropriate size (the length of the output array) and type (byte which is + // uint8_t) + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( + stack.PushValueAndClear(), + outputLength, + g_CLR_RT_WellKnownTypes.m_UInt8)); // get a pointer to the array in the heap block array just created returnArray = stack.TopValue().DereferenceArray()->GetFirstElement(); @@ -581,7 +591,7 @@ HRESULT Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZAR NANOCLR_NOCLEANUP(); } -double Library_corlib_native_System_Convert::GetDoubleFractionalPart(char* str, int length) +double Library_corlib_native_System_Convert::GetDoubleFractionalPart(char *str, int length) { double place = 1; double returnValue = 0.0; @@ -597,7 +607,7 @@ double Library_corlib_native_System_Convert::GetDoubleFractionalPart(char* str, return returnValue; } -int64_t Library_corlib_native_System_Convert::GetIntegerPart(char* str, int length) +int64_t Library_corlib_native_System_Convert::GetIntegerPart(char *str, int length) { int64_t returnValue = 0; @@ -607,7 +617,7 @@ int64_t Library_corlib_native_System_Convert::GetIntegerPart(char* str, int leng str++; // check for terminator, in case this is being called in 'guess' mode - if(*str == '\0') + if (*str == '\0') { break; } @@ -616,35 +626,35 @@ int64_t Library_corlib_native_System_Convert::GetIntegerPart(char* str, int leng return returnValue; } -int64_t Library_corlib_native_System_Convert::GetIntegerFromHexString(char* str) +int64_t Library_corlib_native_System_Convert::GetIntegerFromHexString(char *str) { int64_t returnValue = 0; - if ((*str == '0') && (*(str+1) == 'x')) + if ((*str == '0') && (*(str + 1) == 'x')) { // there a 0x at the begining of the string, so move pointer forward 2 notches str += 2; } - while (*str != '\0') - { - char c = toupper(*str++); + while (*str != '\0') + { + char c = toupper(*str++); - if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A'))) + if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A'))) { // there is an invalid char in the string break; } - c -= '0'; + c -= '0'; - if (c > 9) + if (c > 9) { - c -= 7; + c -= 7; } - returnValue = (returnValue << 4) + c; - } + returnValue = (returnValue << 4) + c; + } - return returnValue; + return returnValue; } diff --git a/src/CLR/Helpers/nanoprintf/nanoprintf.c b/src/CLR/Helpers/nanoprintf/nanoprintf.c index e86ce0cee7..819b580254 100644 --- a/src/CLR/Helpers/nanoprintf/nanoprintf.c +++ b/src/CLR/Helpers/nanoprintf/nanoprintf.c @@ -3,16 +3,16 @@ // Portions Copyright (c) 2001, 2002 Georges Menie. All rights reserved. // Portions Copyright (c) 2009-2013 Daniel D Miller. All rights reserved. // See LICENSE file in the project root for full license information. -// +// // Notes on this implementation: This is a small/fast implementation of printf variants // for double (floating) numbers. It is a compromise of size and speed over capability. // In general the algorithm used in this code can only format a small range of the possible -// values that can be fit in a double. A double can hold roughly +/-1e308, but the code in +// values that can be fit in a double. A double can hold roughly +/-1e308, but the code in // this program uses shifting of 64 bits, so a range of roughly +/-1e18 (2^63). The method -// npf_dsplit_abs supports this limitation and will return a value of "oor" (out-of-range) +// npf_dsplit_abs supports this limitation and will return a value of "oor" (out-of-range) // for numbers over 2^63. It will return zero for any numbers below 2^-63. -// -// See the information here: http://0x80.pl/notesen/2015-12-29-float-to-string.html +// +// See the information here: http://0x80.pl/notesen/2015-12-29-float-to-string.html // /* From c29ea8824cfc429240702abab7060c56e2865564 Mon Sep 17 00:00:00 2001 From: edleno2 Date: Mon, 24 May 2021 11:17:22 -0700 Subject: [PATCH 04/14] Use invalid cast exception for bad casts Unit tests of boxing/unboxing are expecting invalid cast exception. Code was returning generic System.Exception with HR of CLR_E_WRONG_TYPE. Changed code since invalid cast exception is more descriptive of the problem. --- src/CLR/Core/CLR_RT_HeapBlock.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/CLR/Core/CLR_RT_HeapBlock.cpp b/src/CLR/Core/CLR_RT_HeapBlock.cpp index 4940b2cbd1..b53734ce4d 100644 --- a/src/CLR/Core/CLR_RT_HeapBlock.cpp +++ b/src/CLR/Core/CLR_RT_HeapBlock.cpp @@ -878,10 +878,11 @@ HRESULT CLR_RT_HeapBlock::PerformBoxing(const CLR_RT_TypeDef_Instance &cls) * Function parameters: * 1. this - Heap block at the top of evaluation stack. * 2. cls - Runtime Type Definition of the type specified after instruction. - * The functoin takes the object pointed by top of ev. stack. Then it does 3 operatioins: + * + * The function takes the object pointed by top of ev. stack. Then it does 3 operatioins: * 1. Dereferences the object * 2. Validates the type of data kept by object corresponds to type in cls. - * 3. Moves de-referenced date to top of evaluation stack. + * 3. Moves de-referenced data to top of evaluation stack. *******************************************************************************************/ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) @@ -893,7 +894,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) if (this->DataType() != DATATYPE_OBJECT) { - NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); } // Finds the object that keeps the boxed type. @@ -903,7 +904,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) // Validates that src keeps something boxed and the boxed value is VALUE type. if (src->IsBoxed() == false || src->DataType() != DATATYPE_VALUETYPE) { - NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); } // Validates the type of data kept by object corresponds to type in cls. @@ -915,7 +916,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) // This "if" compares underlying type in object and cls. Should be equal in order to continue. if (!(src->DataSize() > 1 && (src[1].DataType() == cls.m_target->dataType))) { - // No luck. The types in src object and specified by cls are different. Need to throw exceptioin. + // No luck. The types in src object and specified by cls are different. Need to throw exception. NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); } } From 63ce22c24d2e77deeb9b8a6af0aeca7b76811c2d Mon Sep 17 00:00:00 2001 From: edleno2 Date: Mon, 24 May 2021 11:33:37 -0700 Subject: [PATCH 05/14] Revert "Use invalid cast exception for bad casts" This reverts commit c29ea8824cfc429240702abab7060c56e2865564. --- src/CLR/Core/CLR_RT_HeapBlock.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/CLR/Core/CLR_RT_HeapBlock.cpp b/src/CLR/Core/CLR_RT_HeapBlock.cpp index b53734ce4d..4940b2cbd1 100644 --- a/src/CLR/Core/CLR_RT_HeapBlock.cpp +++ b/src/CLR/Core/CLR_RT_HeapBlock.cpp @@ -878,11 +878,10 @@ HRESULT CLR_RT_HeapBlock::PerformBoxing(const CLR_RT_TypeDef_Instance &cls) * Function parameters: * 1. this - Heap block at the top of evaluation stack. * 2. cls - Runtime Type Definition of the type specified after instruction. - * - * The function takes the object pointed by top of ev. stack. Then it does 3 operatioins: + * The functoin takes the object pointed by top of ev. stack. Then it does 3 operatioins: * 1. Dereferences the object * 2. Validates the type of data kept by object corresponds to type in cls. - * 3. Moves de-referenced data to top of evaluation stack. + * 3. Moves de-referenced date to top of evaluation stack. *******************************************************************************************/ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) @@ -894,7 +893,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) if (this->DataType() != DATATYPE_OBJECT) { - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } // Finds the object that keeps the boxed type. @@ -904,7 +903,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) // Validates that src keeps something boxed and the boxed value is VALUE type. if (src->IsBoxed() == false || src->DataType() != DATATYPE_VALUETYPE) { - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } // Validates the type of data kept by object corresponds to type in cls. @@ -916,7 +915,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) // This "if" compares underlying type in object and cls. Should be equal in order to continue. if (!(src->DataSize() > 1 && (src[1].DataType() == cls.m_target->dataType))) { - // No luck. The types in src object and specified by cls are different. Need to throw exception. + // No luck. The types in src object and specified by cls are different. Need to throw exceptioin. NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); } } From 0032eeebce54e3e86a003cca3f32bb6942222df8 Mon Sep 17 00:00:00 2001 From: edleno2 Date: Fri, 28 May 2021 12:33:14 -0700 Subject: [PATCH 06/14] Fix unit test problems with CorLibrary Add a FormatException and edits for formatting of int and doubles. Fix #708 --- src/CLR/CorLib/corlib_native.cpp | 10 +- .../CorLib/corlib_native_System_Convert.cpp | 180 +++++++++++------- .../CorLib/corlib_native_System_Exception.cpp | 1 + src/CLR/Core/CLR_RT_HeapBlock.cpp | 4 +- src/CLR/Core/TypeSystem.cpp | 1 + src/CLR/Diagnostics/Info.cpp | 1 + src/CLR/Include/nanoCLR_Runtime.h | 1 + src/CLR/Include/nf_errors_exceptions.h | 158 ++++++++------- 8 files changed, 204 insertions(+), 152 deletions(-) diff --git a/src/CLR/CorLib/corlib_native.cpp b/src/CLR/CorLib/corlib_native.cpp index 7d670a9baf..3627afa4b6 100644 --- a/src/CLR/CorLib/corlib_native.cpp +++ b/src/CLR/CorLib/corlib_native.cpp @@ -526,6 +526,9 @@ static const CLR_RT_MethodHandler method_lookup[] = NULL, NULL, NULL, + NULL, + NULL, + NULL, Library_corlib_native_System_GC::AnyPendingFinalizers___STATIC__BOOLEAN, NULL, Library_corlib_native_System_GC::SuppressFinalize___STATIC__VOID__OBJECT, @@ -1249,6 +1252,9 @@ static const CLR_RT_MethodHandler method_lookup[] = NULL, NULL, NULL, + NULL, + NULL, + NULL, Library_corlib_native_System_GC::AnyPendingFinalizers___STATIC__BOOLEAN, NULL, Library_corlib_native_System_GC::SuppressFinalize___STATIC__VOID__OBJECT, @@ -1480,7 +1486,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib = #if (NANOCLR_REFLECTION == TRUE) - 0x5032B8FF, + 0x1AA8C441, #elif (NANOCLR_REFLECTION == FALSE) @@ -1491,7 +1497,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib = #endif method_lookup, - { 100, 5, 0, 9 } + { 100, 5, 0, 10 } }; // clang-format on diff --git a/src/CLR/CorLib/corlib_native_System_Convert.cpp b/src/CLR/CorLib/corlib_native_System_Convert.cpp index 0c7193d6fd..c0ecc46818 100644 --- a/src/CLR/CorLib/corlib_native_System_Convert.cpp +++ b/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -7,6 +7,7 @@ #include "corlib_native.h" #include #include +#include HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4( CLR_RT_StackFrame &stack) @@ -20,6 +21,8 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING bool isUInt64 = false; bool isSigned = (bool)stack.Arg1().NumericByRef().u1; + bool negReturnExpected = false; + long long minValue = stack.Arg2().NumericByRef().s8; long long maxValue = stack.Arg3().NumericByRef().s8; if (minValue == 0 && maxValue == 0) @@ -34,34 +37,33 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } char *endptr = NULL; + // empty string gets a format exception + if (*str == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); + } + #if (SUPPORT_ANY_BASE_CONVERSION == TRUE) // suport for conversion from any base - // UInt64? => use also strtoull the result will be casted to Int64 - if (isUInt64) + if (*str == '-') { - - // UInt64 can't begin with minus - if (*str == '-') - { - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); - } + negReturnExpected = true; } // convert via strtoll / strtoull + //errno = 0; result = isSigned ? strtoll(str, &endptr, radix) : (long long)strtoull(str, &endptr, radix); - - // TODO: - // If the value in input string is out of the range of representable values - // by a long long int / unsigned long int, the function returns - // LLONG_MAX or LLONG_MIN for signed conversion - // and ULONG_MAX for unsigned conversion - // It is necessary to add a check + //if (errno == + // ERANGE) // catch the case of exceeding signed/unsigned int64. Catch formatting errors in the next statement + //{ + // NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + //} // if no valid conversion endptr is equal str if (str == endptr) { - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } // allow spaces after digits @@ -73,7 +75,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING // should reach end of string no aditional chars if (*endptr != 0) { - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } // the signed values for SByte, Int16 and Int32 are always positive for base 2, 8 or 16 conversions @@ -85,6 +87,12 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING result -= (maxValue + 1) * 2; } + if (negReturnExpected && isSigned == false && result != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + // Check min and max values for the smaller integers - the stroll and stroull will catch int64 excesses if (!isUInt64 && !isSigned && (uint64_t)result > (uint64_t)maxValue) { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); @@ -104,16 +112,10 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING if (radix == 10) { // conversion from base 10 - bool negReturnExpected = false; + // check for minus sign if (*str == '-') { - if (isSigned == false) - { - // Can not use negative string with unsigned interface. This exception is just fail safe - the - // callers of this native method are checking and throwing a better formatted exception - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); - } negReturnExpected = true; str++; } @@ -138,7 +140,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING { break; } - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); // non-numeric (and not trailing space) + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); // non-numeric (and not trailing space) } intPart = (intPart * 10) + (*str - '0'); // advance the digits and add the current number if (intPart < lastValue) // the above operation overflowed the value @@ -153,23 +155,29 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } } // intPart now holds a positive number from the string. - result = (int64_t)intPart; // this MAY have made the result negative by overflowing the buffer - which we do - // for uint64 logic if (negReturnExpected) { - result *= -1; - if (result < minValue) + if (isSigned == false && intPart > 0) // it's ok to use -0 even for unsigned types, but otherwise - NO. + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + if (intPart > (uint64_t)(minValue * -1)) // too big to make a negative value? { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); } + result = intPart * -1; } else { - if (isUInt64 == false // result will be negative for large uints, and we checked for overflow above - && result > maxValue) + if (isUInt64 == false // result will be negative for large uints, and we checked for overflow above + && intPart > (uint64_t)maxValue) { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); } + result = + (int64_t)intPart; // this MAY have made the result negative by overflowing the buffer - which we do + // for uint64 logic. The c# code will cast the int64 to uint64 removing the sign } } else if (radix == 16) @@ -195,13 +203,42 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN NANOCLR_HEADER(); { char *str = (char *)stack.Arg0().RecoverString(); + // skip spaces before digits + while (*str == ' ') + { + str++; + } + + // empty string gets a format exception + if (*str == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); + } #if (SUPPORT_ANY_BASE_CONVERSION == TRUE) // suport for conversion from any base + char *endptr = str; + double returnValue = strtod(str, &endptr); // notice we don't try to catch errno=ERANGE - IEEE574 says overflows + // should just convert to infinity values + if (endptr == str) // didn't parse the string completely + { + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); + } + // allow spaces after digits + while (*endptr == ' ') + { + endptr++; + } - stack.SetResult_R8(strtod(str, nullptr)); + // should reach end of string no aditional chars + if (*endptr != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); + } + + stack.SetResult_R8(returnValue); } - NANOCLR_NOCLEANUP_NOLABEL(); + NANOCLR_NOCLEANUP(); #else // support for conversion from base 10 and 16 (partial) @@ -225,14 +262,16 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN case '-': if (exponentialSign == -1) { - if (length == 0) + if (length == 0 && hasMinusSign == false) { hasMinusSign = true; + str++; // point past the leading sign + length--; // don't count this in the length } else { // found a minus signal NOT at the start of the string - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } } else @@ -244,7 +283,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN else { // found a minus signal NOT at the start of the exponent - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } } break; @@ -252,14 +291,16 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN case '+': if (exponentialSign == -1) { - if (length == 0) + if (length == 0 && hasPlusSign == false) { hasPlusSign = true; + str++; // point past the leading sign + length--; // don't count this in the length } else { // found a plus signal NOT at the start of the string - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } } else @@ -271,7 +312,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN else { // found a plus signal NOT at the start of the exponent - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } } break; @@ -284,7 +325,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN else { // already found a decimal point, can't have another - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } break; @@ -297,15 +338,15 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN else { // already found a exponential sign, can't have another - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } break; default: - if (*temp < '0' && *temp > '9') + if (*temp < '0' || *temp > '9') { // there is an invalid char in the string - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } } length++; @@ -324,36 +365,40 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN // string starts with the decimal point, only has fractional part returnValue = GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); } - else if (hasMinusSign || hasPlusSign) - { - // string starts with sign and... - - if (decimalPoint == 1) - { - // ... is followed by a decimal point, only has fractional part - returnValue = - GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); - } - else - { - // ... has integer and fractional parts - returnValue = GetIntegerPart(str + 1, decimalPoint - 1); - returnValue = - (returnValue + - GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1))); - } - - if (hasMinusSign) - { - returnValue *= -1; - } - } + // else if (hasMinusSign || hasPlusSign) + //{ + // // string starts with sign and... + + // if (decimalPoint == 1) + // { + // // ... is followed by a decimal point, only has fractional part + // returnValue = + // GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); + // } + // else + // { + // // ... has integer and fractional parts + // returnValue = GetIntegerPart(str + 1, decimalPoint - 1); + // returnValue = + // (returnValue + + // GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1))); + // } + + // if (hasMinusSign) + // { + // returnValue *= -1; + // } + //} else { // string has integer and fractional parts returnValue = GetIntegerPart(str, decimalPoint); returnValue = returnValue + GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); + if (hasMinusSign) + { + returnValue *= -1; + } } // exponential part found? @@ -377,6 +422,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN stack.SetResult_R8(returnValue); } + NANOCLR_NOCLEANUP(); #endif // defined(SUPPORT_ANY_BASE_CONVERSION) diff --git a/src/CLR/CorLib/corlib_native_System_Exception.cpp b/src/CLR/CorLib/corlib_native_System_Exception.cpp index ebac14d26c..4cc1caff22 100644 --- a/src/CLR/CorLib/corlib_native_System_Exception.cpp +++ b/src/CLR/CorLib/corlib_native_System_Exception.cpp @@ -22,6 +22,7 @@ static const ExceptionLookup c_ExceptionLookup[] = { EL(CLR_E_OUT_OF_RANGE, m_ArgumentOutOfRangeException), EL(CLR_E_INDEX_OUT_OF_RANGE, m_IndexOutOfRangeException), EL(CLR_E_INVALID_CAST, m_InvalidCastException), + EL(CLR_E_FORMAT_EXCEPTION, m_FormatException), EL(CLR_E_INVALID_OPERATION, m_InvalidOperationException), EL(CLR_E_NOT_SUPPORTED, m_NotSupportedException), EL(CLR_E_NOTIMPL, m_NotImplementedException), diff --git a/src/CLR/Core/CLR_RT_HeapBlock.cpp b/src/CLR/Core/CLR_RT_HeapBlock.cpp index 4940b2cbd1..bad1178b2c 100644 --- a/src/CLR/Core/CLR_RT_HeapBlock.cpp +++ b/src/CLR/Core/CLR_RT_HeapBlock.cpp @@ -893,7 +893,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) if (this->DataType() != DATATYPE_OBJECT) { - NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); } // Finds the object that keeps the boxed type. @@ -903,7 +903,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls) // Validates that src keeps something boxed and the boxed value is VALUE type. if (src->IsBoxed() == false || src->DataType() != DATATYPE_VALUETYPE) { - NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); } // Validates the type of data kept by object corresponds to type in cls. diff --git a/src/CLR/Core/TypeSystem.cpp b/src/CLR/Core/TypeSystem.cpp index cc49a28321..d24d174994 100644 --- a/src/CLR/Core/TypeSystem.cpp +++ b/src/CLR/Core/TypeSystem.cpp @@ -2789,6 +2789,7 @@ static const TypeIndexLookup c_TypeIndexLookup[] = { TIL("System", "Exception", m_Exception), TIL("System", "IndexOutOfRangeException", m_IndexOutOfRangeException), TIL("System", "InvalidCastException", m_InvalidCastException), + TIL("System", "FormatException", m_FormatException), TIL("System", "InvalidOperationException", m_InvalidOperationException), TIL("System", "NotSupportedException", m_NotSupportedException), TIL("System", "NotImplementedException", m_NotImplementedException), diff --git a/src/CLR/Diagnostics/Info.cpp b/src/CLR/Diagnostics/Info.cpp index 9521250efc..e29adfb54d 100644 --- a/src/CLR/Diagnostics/Info.cpp +++ b/src/CLR/Diagnostics/Info.cpp @@ -964,6 +964,7 @@ const char *CLR_RT_DUMP::GETERRORMESSAGE(HRESULT hrError) CASE_HRESULT_TO_STRING(CLR_E_TYPE_UNAVAILABLE); CASE_HRESULT_TO_STRING(CLR_E_INVALID_CAST); CASE_HRESULT_TO_STRING(CLR_E_OUT_OF_RANGE); + CASE_HRESULT_TO_STRING(CLR_E_FORMAT_EXCEPTION); CASE_HRESULT_TO_STRING(CLR_E_SERIALIZATION_VIOLATION); CASE_HRESULT_TO_STRING(CLR_E_SERIALIZATION_BADSTREAM); CASE_HRESULT_TO_STRING(CLR_E_DIVIDE_BY_ZERO); diff --git a/src/CLR/Include/nanoCLR_Runtime.h b/src/CLR/Include/nanoCLR_Runtime.h index d34919c1df..0951d8a28b 100644 --- a/src/CLR/Include/nanoCLR_Runtime.h +++ b/src/CLR/Include/nanoCLR_Runtime.h @@ -1525,6 +1525,7 @@ struct CLR_RT_WellKnownTypes CLR_RT_TypeDef_Index m_ThreadAbortException; CLR_RT_TypeDef_Index m_InvalidOperationException; CLR_RT_TypeDef_Index m_InvalidCastException; + CLR_RT_TypeDef_Index m_FormatException; CLR_RT_TypeDef_Index m_NotSupportedException; CLR_RT_TypeDef_Index m_NotImplementedException; CLR_RT_TypeDef_Index m_NullReferenceException; diff --git a/src/CLR/Include/nf_errors_exceptions.h b/src/CLR/Include/nf_errors_exceptions.h index 479b6b0095..a5b051c010 100644 --- a/src/CLR/Include/nf_errors_exceptions.h +++ b/src/CLR/Include/nf_errors_exceptions.h @@ -14,9 +14,8 @@ typedef int HRESULT; // Severity values // -#define SEVERITY_SUCCESS 0 -#define SEVERITY_ERROR 1 - +#define SEVERITY_SUCCESS 0 +#define SEVERITY_ERROR 1 // // Generic test for success on any status value (non-negative numbers @@ -29,143 +28,140 @@ typedef int HRESULT; // and the inverse // -#define FAILED(Status) ((HRESULT)(Status)<0) - +#define FAILED(Status) ((HRESULT)(Status) < 0) // // Success codes // -#define S_OK ((HRESULT)0x00000000L) -#define S_FALSE ((HRESULT)0x00000001L) - +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) // // Return the code // -#define HRESULT_CODE(hr) ((hr) & 0xFFFF) +#define HRESULT_CODE(hr) ((hr)&0xFFFF) // // Return the facility // -#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) +#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) // // Return the severity // -#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) +#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) // // Create an HRESULT value from component pieces // -#define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) +#define MAKE_HRESULT(sev, fac, code) \ + ((HRESULT)(((unsigned long)(sev) << 31) | ((unsigned long)(fac) << 16) | ((unsigned long)(code)))) #endif // !defined(WIN32) && !defined(_WIN32) //--// // -// These are denormalized HRESULTs, only the 8 most significant bits are set, to allow use of MOV ,# by the compiler. +// These are denormalized HRESULTs, only the 8 most significant bits are set, to allow use of MOV ,# by the +// compiler. // -#define CLR_E_UNKNOWN_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0100, 0x0000 ) -#define CLR_E_UNSUPPORTED_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0200, 0x0000 ) - -#define CLR_E_STACK_OVERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1100, 0x0000 ) -#define CLR_E_STACK_UNDERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1200, 0x0000 ) +#define CLR_E_UNKNOWN_INSTRUCTION MAKE_HRESULT(SEVERITY_ERROR, 0x0100, 0x0000) +#define CLR_E_UNSUPPORTED_INSTRUCTION MAKE_HRESULT(SEVERITY_ERROR, 0x0200, 0x0000) -#define CLR_E_ENTRY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x1500, 0x0000 ) -#define CLR_E_ASSM_WRONG_CHECKSUM MAKE_HRESULT( SEVERITY_ERROR , 0x1600, 0x0000 ) -#define CLR_E_ASSM_PATCHING_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x1700, 0x0000 ) -#define CLR_E_SHUTTING_DOWN MAKE_HRESULT( SEVERITY_ERROR , 0x1800, 0x0000 ) -#define CLR_E_OBJECT_DISPOSED MAKE_HRESULT( SEVERITY_ERROR , 0x1900, 0x0000 ) -#define CLR_E_WATCHDOG_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x1A00, 0x0000 ) +#define CLR_E_STACK_OVERFLOW MAKE_HRESULT(SEVERITY_ERROR, 0x1100, 0x0000) +#define CLR_E_STACK_UNDERFLOW MAKE_HRESULT(SEVERITY_ERROR, 0x1200, 0x0000) -#define CLR_E_NULL_REFERENCE MAKE_HRESULT( SEVERITY_ERROR , 0x2100, 0x0000 ) -#define CLR_E_WRONG_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x2200, 0x0000 ) -#define CLR_E_TYPE_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x2300, 0x0000 ) -#define CLR_E_INVALID_CAST MAKE_HRESULT( SEVERITY_ERROR , 0x2400, 0x0000 ) -#define CLR_E_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2500, 0x0000 ) +#define CLR_E_ENTRY_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x1500, 0x0000) +#define CLR_E_ASSM_WRONG_CHECKSUM MAKE_HRESULT(SEVERITY_ERROR, 0x1600, 0x0000) +#define CLR_E_ASSM_PATCHING_NOT_SUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x1700, 0x0000) +#define CLR_E_SHUTTING_DOWN MAKE_HRESULT(SEVERITY_ERROR, 0x1800, 0x0000) +#define CLR_E_OBJECT_DISPOSED MAKE_HRESULT(SEVERITY_ERROR, 0x1900, 0x0000) +#define CLR_E_WATCHDOG_TIMEOUT MAKE_HRESULT(SEVERITY_ERROR, 0x1A00, 0x0000) -#define CLR_E_SERIALIZATION_VIOLATION MAKE_HRESULT( SEVERITY_ERROR , 0x2700, 0x0000 ) -#define CLR_E_SERIALIZATION_BADSTREAM MAKE_HRESULT( SEVERITY_ERROR , 0x2800, 0x0000 ) -#define CLR_E_INDEX_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2900, 0x0000 ) +#define CLR_E_NULL_REFERENCE MAKE_HRESULT(SEVERITY_ERROR, 0x2100, 0x0000) +#define CLR_E_WRONG_TYPE MAKE_HRESULT(SEVERITY_ERROR, 0x2200, 0x0000) +#define CLR_E_TYPE_UNAVAILABLE MAKE_HRESULT(SEVERITY_ERROR, 0x2300, 0x0000) +#define CLR_E_INVALID_CAST MAKE_HRESULT(SEVERITY_ERROR, 0x2400, 0x0000) +#define CLR_E_OUT_OF_RANGE MAKE_HRESULT(SEVERITY_ERROR, 0x2500, 0x0000) +#define CLR_E_FORMAT_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x2600, 0x0000) +#define CLR_E_SERIALIZATION_VIOLATION MAKE_HRESULT(SEVERITY_ERROR, 0x2700, 0x0000) +#define CLR_E_SERIALIZATION_BADSTREAM MAKE_HRESULT(SEVERITY_ERROR, 0x2800, 0x0000) +#define CLR_E_INDEX_OUT_OF_RANGE MAKE_HRESULT(SEVERITY_ERROR, 0x2900, 0x0000) -#define CLR_E_DIVIDE_BY_ZERO MAKE_HRESULT( SEVERITY_ERROR , 0x3100, 0x0000 ) +#define CLR_E_DIVIDE_BY_ZERO MAKE_HRESULT(SEVERITY_ERROR, 0x3100, 0x0000) -#define CLR_E_BUSY MAKE_HRESULT( SEVERITY_ERROR , 0x3300, 0x0000 ) +#define CLR_E_BUSY MAKE_HRESULT(SEVERITY_ERROR, 0x3300, 0x0000) -#define CLR_E_PROCESS_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4100, 0x0000 ) +#define CLR_E_PROCESS_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x4100, 0x0000) -#define CLR_E_THREAD_WAITING MAKE_HRESULT( SEVERITY_ERROR , 0x4200, 0x0000 ) +#define CLR_E_THREAD_WAITING MAKE_HRESULT(SEVERITY_ERROR, 0x4200, 0x0000) -#define CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4400, 0x0000 ) +#define CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x4400, 0x0000) -#define CLR_E_APPDOMAIN_EXITED MAKE_HRESULT( SEVERITY_ERROR , 0x4800, 0x0000 ) -#define CLR_E_APPDOMAIN_MARSHAL_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4900, 0x0000 ) -#define CLR_E_NOTIMPL MAKE_HRESULT( SEVERITY_ERROR , 0x4a00, 0x0000 ) +#define CLR_E_APPDOMAIN_EXITED MAKE_HRESULT(SEVERITY_ERROR, 0x4800, 0x0000) +#define CLR_E_APPDOMAIN_MARSHAL_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x4900, 0x0000) +#define CLR_E_NOTIMPL MAKE_HRESULT(SEVERITY_ERROR, 0x4a00, 0x0000) -#define CLR_E_UNKNOWN_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x4d00, 0x0000 ) -#define CLR_E_ARGUMENT_NULL MAKE_HRESULT( SEVERITY_ERROR , 0x4e00, 0x0000 ) -#define CLR_E_IO MAKE_HRESULT( SEVERITY_ERROR , 0x4f00, 0x0000 ) - -#define CLR_E_ENTRYPOINT_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x5000, 0x0000 ) -#define CLR_E_DRIVER_NOT_REGISTERED MAKE_HRESULT( SEVERITY_ERROR , 0x5100, 0x0000 ) +#define CLR_E_UNKNOWN_TYPE MAKE_HRESULT(SEVERITY_ERROR, 0x4d00, 0x0000) +#define CLR_E_ARGUMENT_NULL MAKE_HRESULT(SEVERITY_ERROR, 0x4e00, 0x0000) +#define CLR_E_IO MAKE_HRESULT(SEVERITY_ERROR, 0x4f00, 0x0000) +#define CLR_E_ENTRYPOINT_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x5000, 0x0000) +#define CLR_E_DRIVER_NOT_REGISTERED MAKE_HRESULT(SEVERITY_ERROR, 0x5100, 0x0000) // // Gp IO error codes // -#define CLR_E_PIN_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x5400, 0x0000 ) -#define CLR_E_PIN_DEAD MAKE_HRESULT( SEVERITY_ERROR , 0x5500, 0x0000 ) -#define CLR_E_INVALID_OPERATION MAKE_HRESULT( SEVERITY_ERROR , 0x5600, 0x0000 ) -#define CLR_E_WRONG_INTERRUPT_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x5700, 0x0000 ) -#define CLR_E_NO_INTERRUPT MAKE_HRESULT( SEVERITY_ERROR , 0x5800, 0x0000 ) -#define CLR_E_DISPATCHER_ACTIVE MAKE_HRESULT( SEVERITY_ERROR , 0x5900, 0x0000 ) +#define CLR_E_PIN_UNAVAILABLE MAKE_HRESULT(SEVERITY_ERROR, 0x5400, 0x0000) +#define CLR_E_PIN_DEAD MAKE_HRESULT(SEVERITY_ERROR, 0x5500, 0x0000) +#define CLR_E_INVALID_OPERATION MAKE_HRESULT(SEVERITY_ERROR, 0x5600, 0x0000) +#define CLR_E_WRONG_INTERRUPT_TYPE MAKE_HRESULT(SEVERITY_ERROR, 0x5700, 0x0000) +#define CLR_E_NO_INTERRUPT MAKE_HRESULT(SEVERITY_ERROR, 0x5800, 0x0000) +#define CLR_E_DISPATCHER_ACTIVE MAKE_HRESULT(SEVERITY_ERROR, 0x5900, 0x0000) // -// IO error codes +// IO error codes // (Keep in-sync with IOExceptionErrorCode enum in IOException.cs) // -#define CLR_E_FILE_IO MAKE_HRESULT( SEVERITY_ERROR , 0x6000, 0x0000 ) -#define CLR_E_INVALID_DRIVER MAKE_HRESULT( SEVERITY_ERROR , 0x6100, 0x0000 ) -#define CLR_E_FILE_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6200, 0x0000 ) -#define CLR_E_DIRECTORY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6300, 0x0000 ) -#define CLR_E_VOLUME_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6400, 0x0000 ) -#define CLR_E_PATH_TOO_LONG MAKE_HRESULT( SEVERITY_ERROR , 0x6500, 0x0000 ) -#define CLR_E_DIRECTORY_NOT_EMPTY MAKE_HRESULT( SEVERITY_ERROR , 0x6600, 0x0000 ) -#define CLR_E_UNAUTHORIZED_ACCESS MAKE_HRESULT( SEVERITY_ERROR , 0x6700, 0x0000 ) -#define CLR_E_PATH_ALREADY_EXISTS MAKE_HRESULT( SEVERITY_ERROR , 0x6800, 0x0000 ) -#define CLR_E_TOO_MANY_OPEN_HANDLES MAKE_HRESULT( SEVERITY_ERROR , 0x6900, 0x0000 ) +#define CLR_E_FILE_IO MAKE_HRESULT(SEVERITY_ERROR, 0x6000, 0x0000) +#define CLR_E_INVALID_DRIVER MAKE_HRESULT(SEVERITY_ERROR, 0x6100, 0x0000) +#define CLR_E_FILE_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x6200, 0x0000) +#define CLR_E_DIRECTORY_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x6300, 0x0000) +#define CLR_E_VOLUME_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x6400, 0x0000) +#define CLR_E_PATH_TOO_LONG MAKE_HRESULT(SEVERITY_ERROR, 0x6500, 0x0000) +#define CLR_E_DIRECTORY_NOT_EMPTY MAKE_HRESULT(SEVERITY_ERROR, 0x6600, 0x0000) +#define CLR_E_UNAUTHORIZED_ACCESS MAKE_HRESULT(SEVERITY_ERROR, 0x6700, 0x0000) +#define CLR_E_PATH_ALREADY_EXISTS MAKE_HRESULT(SEVERITY_ERROR, 0x6800, 0x0000) +#define CLR_E_TOO_MANY_OPEN_HANDLES MAKE_HRESULT(SEVERITY_ERROR, 0x6900, 0x0000) // // General error codes // -#define CLR_E_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x7500, 0x0000 ) -#define CLR_E_BUFFER_TOO_SMALL MAKE_HRESULT( SEVERITY_ERROR , 0x7600, 0x0000 ) -#define CLR_E_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7700, 0x0000 ) -#define CLR_E_HMAC_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7701, 0x0000 ) -#define CLR_E_RESCHEDULE MAKE_HRESULT( SEVERITY_ERROR , 0x7800, 0x0000 ) +#define CLR_E_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x7500, 0x0000) +#define CLR_E_BUFFER_TOO_SMALL MAKE_HRESULT(SEVERITY_ERROR, 0x7600, 0x0000) +#define CLR_E_NOT_SUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x7700, 0x0000) +#define CLR_E_HMAC_NOT_SUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x7701, 0x0000) +#define CLR_E_RESCHEDULE MAKE_HRESULT(SEVERITY_ERROR, 0x7800, 0x0000) -#define CLR_E_OUT_OF_MEMORY MAKE_HRESULT( SEVERITY_ERROR , 0x7A00, 0x0000 ) -#define CLR_E_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_ERROR , 0x7B00, 0x0000 ) +#define CLR_E_OUT_OF_MEMORY MAKE_HRESULT(SEVERITY_ERROR, 0x7A00, 0x0000) +#define CLR_E_RESTART_EXECUTION MAKE_HRESULT(SEVERITY_ERROR, 0x7B00, 0x0000) -#define CLR_E_INVALID_PARAMETER MAKE_HRESULT( SEVERITY_ERROR , 0x7D00, 0x0000 ) -#define CLR_E_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x7E00, 0x0000 ) -#define CLR_E_FAIL MAKE_HRESULT( SEVERITY_ERROR , 0x7F00, 0x0000 ) +#define CLR_E_INVALID_PARAMETER MAKE_HRESULT(SEVERITY_ERROR, 0x7D00, 0x0000) +#define CLR_E_TIMEOUT MAKE_HRESULT(SEVERITY_ERROR, 0x7E00, 0x0000) +#define CLR_E_FAIL MAKE_HRESULT(SEVERITY_ERROR, 0x7F00, 0x0000) //--// -#define CLR_S_THREAD_EXITED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0100, 0x0000 ) -#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0200, 0x0000 ) -#define CLR_S_NO_READY_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0300, 0x0000 ) -#define CLR_S_NO_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0400, 0x0000 ) -#define CLR_S_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_SUCCESS, 0x0500, 0x0000 ) - - -#endif // __NF_ERRORS_H__ +#define CLR_S_THREAD_EXITED MAKE_HRESULT(SEVERITY_SUCCESS, 0x0100, 0x0000) +#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT(SEVERITY_SUCCESS, 0x0200, 0x0000) +#define CLR_S_NO_READY_THREADS MAKE_HRESULT(SEVERITY_SUCCESS, 0x0300, 0x0000) +#define CLR_S_NO_THREADS MAKE_HRESULT(SEVERITY_SUCCESS, 0x0400, 0x0000) +#define CLR_S_RESTART_EXECUTION MAKE_HRESULT(SEVERITY_SUCCESS, 0x0500, 0x0000) +#endif // __NF_ERRORS_H__ From 079319a64c63e66231fe185fde75629687f6bdec Mon Sep 17 00:00:00 2001 From: edleno2 Date: Fri, 28 May 2021 19:55:35 -0700 Subject: [PATCH 07/14] Fix building for ESP32 and STM32 Win32 builds worked, but not ESP32 and STM32. Fixed (1) missing API in target cmake-variants.json; (2) moved location of declaration to allow it to be defined before redefines happen for "errno". Fix #708 --- .../CorLib/corlib_native_System_Convert.cpp | 19 ++++++++++--------- .../cmake-variants.json | 1 + 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/CLR/CorLib/corlib_native_System_Convert.cpp b/src/CLR/CorLib/corlib_native_System_Convert.cpp index c0ecc46818..07789203a3 100644 --- a/src/CLR/CorLib/corlib_native_System_Convert.cpp +++ b/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -4,10 +4,10 @@ // See LICENSE file in the project root for full license information. // +#include // this appears first so that errno macro can get redefined in other system headers used in corlib_native.h #include "corlib_native.h" #include #include -#include HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4( CLR_RT_StackFrame &stack) @@ -42,7 +42,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING { NANOCLR_SET_AND_LEAVE(CLR_E_FORMAT_EXCEPTION); } - + #if (SUPPORT_ANY_BASE_CONVERSION == TRUE) // suport for conversion from any base @@ -52,13 +52,14 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } // convert via strtoll / strtoull - //errno = 0; + + errno = 0; result = isSigned ? strtoll(str, &endptr, radix) : (long long)strtoull(str, &endptr, radix); - //if (errno == - // ERANGE) // catch the case of exceeding signed/unsigned int64. Catch formatting errors in the next statement - //{ - // NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); - //} + if (errno == + ERANGE) // catch the case of exceeding signed/unsigned int64. Catch formatting errors in the next statement + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } // if no valid conversion endptr is equal str if (str == endptr) @@ -170,7 +171,7 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } else { - if (isUInt64 == false // result will be negative for large uints, and we checked for overflow above + if (isUInt64 == false // result will be negative for large uints, and we checked for overflow above && intPart > (uint64_t)maxValue) { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); diff --git a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json index 4842cc1b34..c394ff177b 100644 --- a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json +++ b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json @@ -53,6 +53,7 @@ "API_System.Device.I2c": "ON", "API_Windows.Devices.Pwm": "ON", "API_Windows.Devices.SerialCommunication": "ON", + "API_System.IO.Ports": "ON", "API_Windows.Devices.Adc": "ON", "API_nanoFramework.Devices.OneWire": "ON", "API_nanoFramework.Devices.Can": "ON", From 9b1b92d7adf1dd4eaa4d62b5cec6670dc4bcb55f Mon Sep 17 00:00:00 2001 From: edleno2 Date: Fri, 28 May 2021 20:01:41 -0700 Subject: [PATCH 08/14] Removed code that was commented out in refactoring Some code was simplified by combing the handling of both positive and negative results into one routine that checked for adjusting the sign at the end just before returning a value. Remove the code that was commented out now that all unit testing is complete. Fix #708 --- .../CorLib/corlib_native_System_Convert.cpp | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/src/CLR/CorLib/corlib_native_System_Convert.cpp b/src/CLR/CorLib/corlib_native_System_Convert.cpp index 07789203a3..e6ff8d783c 100644 --- a/src/CLR/CorLib/corlib_native_System_Convert.cpp +++ b/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -366,30 +366,6 @@ HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRIN // string starts with the decimal point, only has fractional part returnValue = GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); } - // else if (hasMinusSign || hasPlusSign) - //{ - // // string starts with sign and... - - // if (decimalPoint == 1) - // { - // // ... is followed by a decimal point, only has fractional part - // returnValue = - // GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1)); - // } - // else - // { - // // ... has integer and fractional parts - // returnValue = GetIntegerPart(str + 1, decimalPoint - 1); - // returnValue = - // (returnValue + - // GetDoubleFractionalPart((str + decimalPoint + 1), (endOrExponentialPart - decimalPoint - 1))); - // } - - // if (hasMinusSign) - // { - // returnValue *= -1; - // } - //} else { // string has integer and fractional parts From f37abe2349dca68911360d571ce068de44280157 Mon Sep 17 00:00:00 2001 From: edleno2 Date: Sat, 29 May 2021 12:34:17 -0700 Subject: [PATCH 09/14] update NoReflection checksum for mscorlib Fix #708 --- src/CLR/CorLib/corlib_native.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CLR/CorLib/corlib_native.cpp b/src/CLR/CorLib/corlib_native.cpp index 3627afa4b6..308c13da0e 100644 --- a/src/CLR/CorLib/corlib_native.cpp +++ b/src/CLR/CorLib/corlib_native.cpp @@ -1490,7 +1490,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib = #elif (NANOCLR_REFLECTION == FALSE) - 0x6553AB61, + 0x0D2A29C8, #else #error "NANOCLR_REFLECTION has to be define either TRUE or FALSE. Check the build options." From 9573b5474c3c4fb6a75e853169deea359e0d1345 Mon Sep 17 00:00:00 2001 From: edleno2 Date: Sat, 29 May 2021 12:47:45 -0700 Subject: [PATCH 10/14] Revert change to cmake-variants.json --- targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json | 1 - 1 file changed, 1 deletion(-) diff --git a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json index c394ff177b..4842cc1b34 100644 --- a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json +++ b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json @@ -53,7 +53,6 @@ "API_System.Device.I2c": "ON", "API_Windows.Devices.Pwm": "ON", "API_Windows.Devices.SerialCommunication": "ON", - "API_System.IO.Ports": "ON", "API_Windows.Devices.Adc": "ON", "API_nanoFramework.Devices.OneWire": "ON", "API_nanoFramework.Devices.Can": "ON", From 815921fc48cf34dbdfc6a93823a2a6db927ac82b Mon Sep 17 00:00:00 2001 From: edleno2 Date: Sat, 29 May 2021 13:17:58 -0700 Subject: [PATCH 11/14] Undo format changes caused by clang format. --- src/CLR/Include/nf_errors_exceptions.h | 139 +++++++++++++------------ 1 file changed, 72 insertions(+), 67 deletions(-) diff --git a/src/CLR/Include/nf_errors_exceptions.h b/src/CLR/Include/nf_errors_exceptions.h index a5b051c010..c2fd03f0cf 100644 --- a/src/CLR/Include/nf_errors_exceptions.h +++ b/src/CLR/Include/nf_errors_exceptions.h @@ -65,103 +65,108 @@ typedef int HRESULT; //--// +// clang-format off + // -// These are denormalized HRESULTs, only the 8 most significant bits are set, to allow use of MOV ,# by the -// compiler. +// These are denormalized HRESULTs, only the 8 most significant bits are set, to allow use of MOV ,# by the compiler. // -#define CLR_E_UNKNOWN_INSTRUCTION MAKE_HRESULT(SEVERITY_ERROR, 0x0100, 0x0000) -#define CLR_E_UNSUPPORTED_INSTRUCTION MAKE_HRESULT(SEVERITY_ERROR, 0x0200, 0x0000) +#define CLR_E_UNKNOWN_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0100, 0x0000 ) +#define CLR_E_UNSUPPORTED_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0200, 0x0000 ) + +#define CLR_E_STACK_OVERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1100, 0x0000 ) +#define CLR_E_STACK_UNDERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1200, 0x0000 ) -#define CLR_E_STACK_OVERFLOW MAKE_HRESULT(SEVERITY_ERROR, 0x1100, 0x0000) -#define CLR_E_STACK_UNDERFLOW MAKE_HRESULT(SEVERITY_ERROR, 0x1200, 0x0000) +#define CLR_E_ENTRY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x1500, 0x0000 ) +#define CLR_E_ASSM_WRONG_CHECKSUM MAKE_HRESULT( SEVERITY_ERROR , 0x1600, 0x0000 ) +#define CLR_E_ASSM_PATCHING_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x1700, 0x0000 ) +#define CLR_E_SHUTTING_DOWN MAKE_HRESULT( SEVERITY_ERROR , 0x1800, 0x0000 ) +#define CLR_E_OBJECT_DISPOSED MAKE_HRESULT( SEVERITY_ERROR , 0x1900, 0x0000 ) +#define CLR_E_WATCHDOG_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x1A00, 0x0000 ) -#define CLR_E_ENTRY_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x1500, 0x0000) -#define CLR_E_ASSM_WRONG_CHECKSUM MAKE_HRESULT(SEVERITY_ERROR, 0x1600, 0x0000) -#define CLR_E_ASSM_PATCHING_NOT_SUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x1700, 0x0000) -#define CLR_E_SHUTTING_DOWN MAKE_HRESULT(SEVERITY_ERROR, 0x1800, 0x0000) -#define CLR_E_OBJECT_DISPOSED MAKE_HRESULT(SEVERITY_ERROR, 0x1900, 0x0000) -#define CLR_E_WATCHDOG_TIMEOUT MAKE_HRESULT(SEVERITY_ERROR, 0x1A00, 0x0000) +#define CLR_E_NULL_REFERENCE MAKE_HRESULT( SEVERITY_ERROR , 0x2100, 0x0000 ) +#define CLR_E_WRONG_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x2200, 0x0000 ) +#define CLR_E_TYPE_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x2300, 0x0000 ) +#define CLR_E_INVALID_CAST MAKE_HRESULT( SEVERITY_ERROR , 0x2400, 0x0000 ) +#define CLR_E_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2500, 0x0000 ) +#define CLR_E_FORMAT_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x2600, 0x0000 ) -#define CLR_E_NULL_REFERENCE MAKE_HRESULT(SEVERITY_ERROR, 0x2100, 0x0000) -#define CLR_E_WRONG_TYPE MAKE_HRESULT(SEVERITY_ERROR, 0x2200, 0x0000) -#define CLR_E_TYPE_UNAVAILABLE MAKE_HRESULT(SEVERITY_ERROR, 0x2300, 0x0000) -#define CLR_E_INVALID_CAST MAKE_HRESULT(SEVERITY_ERROR, 0x2400, 0x0000) -#define CLR_E_OUT_OF_RANGE MAKE_HRESULT(SEVERITY_ERROR, 0x2500, 0x0000) -#define CLR_E_FORMAT_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x2600, 0x0000) -#define CLR_E_SERIALIZATION_VIOLATION MAKE_HRESULT(SEVERITY_ERROR, 0x2700, 0x0000) -#define CLR_E_SERIALIZATION_BADSTREAM MAKE_HRESULT(SEVERITY_ERROR, 0x2800, 0x0000) -#define CLR_E_INDEX_OUT_OF_RANGE MAKE_HRESULT(SEVERITY_ERROR, 0x2900, 0x0000) +#define CLR_E_SERIALIZATION_VIOLATION MAKE_HRESULT( SEVERITY_ERROR , 0x2700, 0x0000 ) +#define CLR_E_SERIALIZATION_BADSTREAM MAKE_HRESULT( SEVERITY_ERROR , 0x2800, 0x0000 ) +#define CLR_E_INDEX_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2900, 0x0000 ) -#define CLR_E_DIVIDE_BY_ZERO MAKE_HRESULT(SEVERITY_ERROR, 0x3100, 0x0000) +#define CLR_E_DIVIDE_BY_ZERO MAKE_HRESULT( SEVERITY_ERROR , 0x3100, 0x0000 ) -#define CLR_E_BUSY MAKE_HRESULT(SEVERITY_ERROR, 0x3300, 0x0000) +#define CLR_E_BUSY MAKE_HRESULT( SEVERITY_ERROR , 0x3300, 0x0000 ) -#define CLR_E_PROCESS_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x4100, 0x0000) +#define CLR_E_PROCESS_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4100, 0x0000 ) -#define CLR_E_THREAD_WAITING MAKE_HRESULT(SEVERITY_ERROR, 0x4200, 0x0000) +#define CLR_E_THREAD_WAITING MAKE_HRESULT( SEVERITY_ERROR , 0x4200, 0x0000 ) -#define CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x4400, 0x0000) +#define CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4400, 0x0000 ) -#define CLR_E_APPDOMAIN_EXITED MAKE_HRESULT(SEVERITY_ERROR, 0x4800, 0x0000) -#define CLR_E_APPDOMAIN_MARSHAL_EXCEPTION MAKE_HRESULT(SEVERITY_ERROR, 0x4900, 0x0000) -#define CLR_E_NOTIMPL MAKE_HRESULT(SEVERITY_ERROR, 0x4a00, 0x0000) +#define CLR_E_APPDOMAIN_EXITED MAKE_HRESULT( SEVERITY_ERROR , 0x4800, 0x0000 ) +#define CLR_E_APPDOMAIN_MARSHAL_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4900, 0x0000 ) +#define CLR_E_NOTIMPL MAKE_HRESULT( SEVERITY_ERROR , 0x4a00, 0x0000 ) -#define CLR_E_UNKNOWN_TYPE MAKE_HRESULT(SEVERITY_ERROR, 0x4d00, 0x0000) -#define CLR_E_ARGUMENT_NULL MAKE_HRESULT(SEVERITY_ERROR, 0x4e00, 0x0000) -#define CLR_E_IO MAKE_HRESULT(SEVERITY_ERROR, 0x4f00, 0x0000) +#define CLR_E_UNKNOWN_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x4d00, 0x0000 ) +#define CLR_E_ARGUMENT_NULL MAKE_HRESULT( SEVERITY_ERROR , 0x4e00, 0x0000 ) +#define CLR_E_IO MAKE_HRESULT( SEVERITY_ERROR , 0x4f00, 0x0000 ) + +#define CLR_E_ENTRYPOINT_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x5000, 0x0000 ) +#define CLR_E_DRIVER_NOT_REGISTERED MAKE_HRESULT( SEVERITY_ERROR , 0x5100, 0x0000 ) -#define CLR_E_ENTRYPOINT_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x5000, 0x0000) -#define CLR_E_DRIVER_NOT_REGISTERED MAKE_HRESULT(SEVERITY_ERROR, 0x5100, 0x0000) // // Gp IO error codes // -#define CLR_E_PIN_UNAVAILABLE MAKE_HRESULT(SEVERITY_ERROR, 0x5400, 0x0000) -#define CLR_E_PIN_DEAD MAKE_HRESULT(SEVERITY_ERROR, 0x5500, 0x0000) -#define CLR_E_INVALID_OPERATION MAKE_HRESULT(SEVERITY_ERROR, 0x5600, 0x0000) -#define CLR_E_WRONG_INTERRUPT_TYPE MAKE_HRESULT(SEVERITY_ERROR, 0x5700, 0x0000) -#define CLR_E_NO_INTERRUPT MAKE_HRESULT(SEVERITY_ERROR, 0x5800, 0x0000) -#define CLR_E_DISPATCHER_ACTIVE MAKE_HRESULT(SEVERITY_ERROR, 0x5900, 0x0000) +#define CLR_E_PIN_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x5400, 0x0000 ) +#define CLR_E_PIN_DEAD MAKE_HRESULT( SEVERITY_ERROR , 0x5500, 0x0000 ) +#define CLR_E_INVALID_OPERATION MAKE_HRESULT( SEVERITY_ERROR , 0x5600, 0x0000 ) +#define CLR_E_WRONG_INTERRUPT_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x5700, 0x0000 ) +#define CLR_E_NO_INTERRUPT MAKE_HRESULT( SEVERITY_ERROR , 0x5800, 0x0000 ) +#define CLR_E_DISPATCHER_ACTIVE MAKE_HRESULT( SEVERITY_ERROR , 0x5900, 0x0000 ) // -// IO error codes +// IO error codes // (Keep in-sync with IOExceptionErrorCode enum in IOException.cs) // -#define CLR_E_FILE_IO MAKE_HRESULT(SEVERITY_ERROR, 0x6000, 0x0000) -#define CLR_E_INVALID_DRIVER MAKE_HRESULT(SEVERITY_ERROR, 0x6100, 0x0000) -#define CLR_E_FILE_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x6200, 0x0000) -#define CLR_E_DIRECTORY_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x6300, 0x0000) -#define CLR_E_VOLUME_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x6400, 0x0000) -#define CLR_E_PATH_TOO_LONG MAKE_HRESULT(SEVERITY_ERROR, 0x6500, 0x0000) -#define CLR_E_DIRECTORY_NOT_EMPTY MAKE_HRESULT(SEVERITY_ERROR, 0x6600, 0x0000) -#define CLR_E_UNAUTHORIZED_ACCESS MAKE_HRESULT(SEVERITY_ERROR, 0x6700, 0x0000) -#define CLR_E_PATH_ALREADY_EXISTS MAKE_HRESULT(SEVERITY_ERROR, 0x6800, 0x0000) -#define CLR_E_TOO_MANY_OPEN_HANDLES MAKE_HRESULT(SEVERITY_ERROR, 0x6900, 0x0000) +#define CLR_E_FILE_IO MAKE_HRESULT( SEVERITY_ERROR , 0x6000, 0x0000 ) +#define CLR_E_INVALID_DRIVER MAKE_HRESULT( SEVERITY_ERROR , 0x6100, 0x0000 ) +#define CLR_E_FILE_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6200, 0x0000 ) +#define CLR_E_DIRECTORY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6300, 0x0000 ) +#define CLR_E_VOLUME_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6400, 0x0000 ) +#define CLR_E_PATH_TOO_LONG MAKE_HRESULT( SEVERITY_ERROR , 0x6500, 0x0000 ) +#define CLR_E_DIRECTORY_NOT_EMPTY MAKE_HRESULT( SEVERITY_ERROR , 0x6600, 0x0000 ) +#define CLR_E_UNAUTHORIZED_ACCESS MAKE_HRESULT( SEVERITY_ERROR , 0x6700, 0x0000 ) +#define CLR_E_PATH_ALREADY_EXISTS MAKE_HRESULT( SEVERITY_ERROR , 0x6800, 0x0000 ) +#define CLR_E_TOO_MANY_OPEN_HANDLES MAKE_HRESULT( SEVERITY_ERROR , 0x6900, 0x0000 ) // // General error codes // -#define CLR_E_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, 0x7500, 0x0000) -#define CLR_E_BUFFER_TOO_SMALL MAKE_HRESULT(SEVERITY_ERROR, 0x7600, 0x0000) -#define CLR_E_NOT_SUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x7700, 0x0000) -#define CLR_E_HMAC_NOT_SUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x7701, 0x0000) -#define CLR_E_RESCHEDULE MAKE_HRESULT(SEVERITY_ERROR, 0x7800, 0x0000) +#define CLR_E_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x7500, 0x0000 ) +#define CLR_E_BUFFER_TOO_SMALL MAKE_HRESULT( SEVERITY_ERROR , 0x7600, 0x0000 ) +#define CLR_E_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7700, 0x0000 ) +#define CLR_E_HMAC_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7701, 0x0000 ) +#define CLR_E_RESCHEDULE MAKE_HRESULT( SEVERITY_ERROR , 0x7800, 0x0000 ) -#define CLR_E_OUT_OF_MEMORY MAKE_HRESULT(SEVERITY_ERROR, 0x7A00, 0x0000) -#define CLR_E_RESTART_EXECUTION MAKE_HRESULT(SEVERITY_ERROR, 0x7B00, 0x0000) +#define CLR_E_OUT_OF_MEMORY MAKE_HRESULT( SEVERITY_ERROR , 0x7A00, 0x0000 ) +#define CLR_E_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_ERROR , 0x7B00, 0x0000 ) -#define CLR_E_INVALID_PARAMETER MAKE_HRESULT(SEVERITY_ERROR, 0x7D00, 0x0000) -#define CLR_E_TIMEOUT MAKE_HRESULT(SEVERITY_ERROR, 0x7E00, 0x0000) -#define CLR_E_FAIL MAKE_HRESULT(SEVERITY_ERROR, 0x7F00, 0x0000) +#define CLR_E_INVALID_PARAMETER MAKE_HRESULT( SEVERITY_ERROR , 0x7D00, 0x0000 ) +#define CLR_E_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x7E00, 0x0000 ) +#define CLR_E_FAIL MAKE_HRESULT( SEVERITY_ERROR , 0x7F00, 0x0000 ) //--// -#define CLR_S_THREAD_EXITED MAKE_HRESULT(SEVERITY_SUCCESS, 0x0100, 0x0000) -#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT(SEVERITY_SUCCESS, 0x0200, 0x0000) -#define CLR_S_NO_READY_THREADS MAKE_HRESULT(SEVERITY_SUCCESS, 0x0300, 0x0000) -#define CLR_S_NO_THREADS MAKE_HRESULT(SEVERITY_SUCCESS, 0x0400, 0x0000) -#define CLR_S_RESTART_EXECUTION MAKE_HRESULT(SEVERITY_SUCCESS, 0x0500, 0x0000) +#define CLR_S_THREAD_EXITED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0100, 0x0000 ) +#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0200, 0x0000 ) +#define CLR_S_NO_READY_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0300, 0x0000 ) +#define CLR_S_NO_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0400, 0x0000 ) +#define CLR_S_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_SUCCESS, 0x0500, 0x0000 ) + +// clang-format off -#endif // __NF_ERRORS_H__ +#endif // __NF_ERRORS_H__ \ No newline at end of file From f16d0bcf6e136f24f7c1d85b9c91aeffe3962a3b Mon Sep 17 00:00:00 2001 From: edleno2 Date: Sat, 29 May 2021 13:50:48 -0700 Subject: [PATCH 12/14] reverted cmake-variants.json change --- targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json | 1 - 1 file changed, 1 deletion(-) diff --git a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json index c394ff177b..4842cc1b34 100644 --- a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json +++ b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json @@ -53,7 +53,6 @@ "API_System.Device.I2c": "ON", "API_Windows.Devices.Pwm": "ON", "API_Windows.Devices.SerialCommunication": "ON", - "API_System.IO.Ports": "ON", "API_Windows.Devices.Adc": "ON", "API_nanoFramework.Devices.OneWire": "ON", "API_nanoFramework.Devices.Can": "ON", From f6d0b1674bccf1405812a59e5f0f08f79879f883 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sat, 29 May 2021 23:12:36 +0100 Subject: [PATCH 13/14] Add missing API's to target files (#1937) ***NO_CI*** --- .vscode/cmake-variants-DEVCONTAINER.json | 3 ++- .vscode/cmake-variants.TEMPLATE.json | 1 + CMake/Modules/FindNF_NativeAssemblies.cmake | 2 +- CMakeSettings.SAMPLE.json | 20 +++++++++++++++++++ CMakeSettings.json | 16 +++++++++++++++ .../cmake-variants.json | 1 + .../TI_CC1352R1_LAUNCHXL/cmake-variants.json | 1 + 7 files changed, 42 insertions(+), 2 deletions(-) diff --git a/.vscode/cmake-variants-DEVCONTAINER.json b/.vscode/cmake-variants-DEVCONTAINER.json index c4fe4cb8b9..afc22af143 100644 --- a/.vscode/cmake-variants-DEVCONTAINER.json +++ b/.vscode/cmake-variants-DEVCONTAINER.json @@ -303,7 +303,7 @@ "API_nanoFramework.System.Text": "ON", "API_Windows.Devices.Wifi": "ON", "API_Windows.Devices.Adc": "ON", - "API_System.Devices.Dac": "OFF", + "API_System.Device.Dac": "OFF", "API_System.IO.FileSystem": "OFF", "API_Windows.Devices.Gpio": "ON", "API_System.Device.Gpio": "ON", @@ -351,6 +351,7 @@ "API_Windows.Devices.Gpio": "ON", "API_System.Device.Gpio": "ON", "API_Windows.Devices.I2c": "ON", + "API_System.Device.I2c": "ON", "API_Windows.Devices.Pwm": "ON", "API_Windows.Devices.SerialCommunication": "ON", "API_System.IO.Ports": "ON", diff --git a/.vscode/cmake-variants.TEMPLATE.json b/.vscode/cmake-variants.TEMPLATE.json index 753a417145..1b62fd6d56 100644 --- a/.vscode/cmake-variants.TEMPLATE.json +++ b/.vscode/cmake-variants.TEMPLATE.json @@ -101,6 +101,7 @@ "API_Windows.Devices.SerialCommunication": "OFF-default-ON-to-add-this-API", "API_System.IO.Ports": "OFF-default-ON-to-add-this-API", "API_Windows.Devices.Spi": "OFF-default-ON-to-add-this-API", + "API_System.Device.Spi": "OFF-default-ON-to-add-this-API", "API_Hardware.Esp32": "OFF-default-ON-to-add-this-API", "API_Hardware.Stm32": "OFF-default-ON-to-add-this-API", "API_nanoFramework.TI.EasyLink": "OFF-default-ON-to-add-this-API", diff --git a/CMake/Modules/FindNF_NativeAssemblies.cmake b/CMake/Modules/FindNF_NativeAssemblies.cmake index 86147a924e..5c7bb1b07a 100644 --- a/CMake/Modules/FindNF_NativeAssemblies.cmake +++ b/CMake/Modules/FindNF_NativeAssemblies.cmake @@ -5,7 +5,7 @@ ############################################################################################ # WHEN ADDING A NEW API add the name that corresponds to the CMake option here -# e.g.: for namespace Windows.Devices.Gpio, the CMake option is 'API_Windows.Devices.Gpio' +# e.g.: for namespace System.Device.Gpio, the CMake option is 'API_System.Device.Gpio' # and the namespace designation is 'Windows.Devices.Gpio' ########################################################################################### diff --git a/CMakeSettings.SAMPLE.json b/CMakeSettings.SAMPLE.json index b3554d6ed2..2ad721229f 100644 --- a/CMakeSettings.SAMPLE.json +++ b/CMakeSettings.SAMPLE.json @@ -213,11 +213,21 @@ "value": "True", "type": "BOOL" }, + { + "name": "API_System.Device.Gpio", + "value": "True", + "type": "BOOL" + }, { "name": "API_Windows.Devices.I2c", "value": "True", "type": "BOOL" }, + { + "name": "API_System.Device.I2c", + "value": "True", + "type": "BOOL" + }, { "name": "API_Windows.Devices.Pwm", "value": "True", @@ -483,11 +493,21 @@ "value": "True", "type": "BOOL" }, + { + "name": "API_System.Device.Gpio", + "value": "True", + "type": "BOOL" + }, { "name": "API_Windows.Devices.I2c", "value": "True", "type": "BOOL" }, + { + "name": "API_System.Device.I2c", + "value": "True", + "type": "BOOL" + }, { "name": "API_Windows.Devices.Pwm", "value": "True", diff --git a/CMakeSettings.json b/CMakeSettings.json index e4c46aeadc..15829b35aa 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -119,6 +119,10 @@ "name": "API_Windows.Devices.Gpio", "value": "ON" }, + { + "name": "API_System.Device.Gpio", + "value": "ON" + }, { "name": "API_Windows.Devices.Spi", "value": "ON" @@ -131,6 +135,10 @@ "name": "API_Windows.Devices.I2c", "value": "ON" }, + { + "name": "API_System.Device.I2c", + "value": "ON" + }, { "name": "API_Windows.Devices.Pwm", "value": "ON" @@ -403,10 +411,18 @@ "name": "API_Windows.Devices.Gpio:BOOL", //OFF-default-ON-to-add-this-API "value": "ON" }, + { + "name": "API_System.Device.Gpio:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, { "name": "API_Windows.Devices.I2c:BOOL", //OFF-default-ON-to-add-this-API "value": "ON" }, + { + "name": "API_System.Device.I2c:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, { "name": "API_Windows.Devices.Pwm:BOOL", //OFF-default-ON-to-add-this-API "value": "ON" diff --git a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json index 4842cc1b34..c394ff177b 100644 --- a/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json +++ b/targets/ChibiOS/ST_STM32F429I_DISCOVERY/cmake-variants.json @@ -53,6 +53,7 @@ "API_System.Device.I2c": "ON", "API_Windows.Devices.Pwm": "ON", "API_Windows.Devices.SerialCommunication": "ON", + "API_System.IO.Ports": "ON", "API_Windows.Devices.Adc": "ON", "API_nanoFramework.Devices.OneWire": "ON", "API_nanoFramework.Devices.Can": "ON", diff --git a/targets/TI-SimpleLink/TI_CC1352R1_LAUNCHXL/cmake-variants.json b/targets/TI-SimpleLink/TI_CC1352R1_LAUNCHXL/cmake-variants.json index cc8d53c12b..12b0d350d1 100644 --- a/targets/TI-SimpleLink/TI_CC1352R1_LAUNCHXL/cmake-variants.json +++ b/targets/TI-SimpleLink/TI_CC1352R1_LAUNCHXL/cmake-variants.json @@ -46,6 +46,7 @@ "API_Windows.Devices.Gpio": "ON", "API_System.Device.Gpio": "ON", "API_Windows.Devices.Spi": "OFF", + "API_System.Device.Spi": "OFF", "API_Windows.Devices.I2c": "OFF", "API_System.Device.I2c": "OFF", "API_Windows.Devices.Pwm": "OFF", From d9afbb2bae130429279ca3a04af7d2c565a212df Mon Sep 17 00:00:00 2001 From: edleno2 Date: Sun, 30 May 2021 23:31:48 -0700 Subject: [PATCH 14/14] Fix strtoll and strtoull to use reentrant versions when needed When compiled with devices that use LWIP for networking certain stdlib routines are required to be reentrant. Cleaned up a little left over formatting in nf_errors_exceptions.h Fix #708 --- .../CorLib/corlib_native_System_Convert.cpp | 19 ++++++++++++------- src/CLR/Include/nf_errors_exceptions.h | 10 +++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/CLR/CorLib/corlib_native_System_Convert.cpp b/src/CLR/CorLib/corlib_native_System_Convert.cpp index 12c2cec0a3..daedb70b83 100644 --- a/src/CLR/CorLib/corlib_native_System_Convert.cpp +++ b/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -4,13 +4,10 @@ // See LICENSE file in the project root for full license information. // -#include // this appears first so that errno macro can get redefined in other system headers used in corlib_native.h #include "corlib_native.h" #include #include - -// need this here instead of the standard "#include " because that brings issues when compiling -extern int errno; +#include // when running with lwip the use of errno is affected by _REENT_ONLY - see below. LWIP is included via corlib_native.h and lower (HAL). Win32 does not use it HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4( CLR_RT_StackFrame &stack) @@ -55,11 +52,19 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING } // convert via strtoll / strtoull - + int error_code; + +#ifdef _REENT_ONLY // Have to use reentrant version of strtoll because lwip sets _REENT_ONLY to require all stdlib calls to be reentrant + _reent reent_data; + reent_data._errno = 0; + result = isSigned ? _strtoll_r(&reent_data, str, &endptr, radix) : (long long)_strtoull_r(&reent_data, str, &endptr, radix); + error_code = (int)reent_data._errno; +#else errno = 0; result = isSigned ? strtoll(str, &endptr, radix) : (long long)strtoull(str, &endptr, radix); - if (errno == - ERANGE) // catch the case of exceeding signed/unsigned int64. Catch formatting errors in the next statement + error_code = errno; +#endif //_REENT_ONLY + if (error_code == ERANGE) // catch the case of exceeding signed/unsigned int64. Catch formatting errors in the next statement { NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); } diff --git a/src/CLR/Include/nf_errors_exceptions.h b/src/CLR/Include/nf_errors_exceptions.h index 8fbad0b291..f230567325 100644 --- a/src/CLR/Include/nf_errors_exceptions.h +++ b/src/CLR/Include/nf_errors_exceptions.h @@ -160,11 +160,11 @@ typedef int HRESULT; //--// -#define CLR_S_THREAD_EXITED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0100, 0x0000 ) -#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0200, 0x0000 ) -#define CLR_S_NO_READY_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0300, 0x0000 ) -#define CLR_S_NO_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0400, 0x0000 ) -#define CLR_S_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_SUCCESS, 0x0500, 0x0000 ) +#define CLR_S_THREAD_EXITED MAKE_HRESULT(SEVERITY_SUCCESS, 0x0100, 0x0000) +#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT(SEVERITY_SUCCESS, 0x0200, 0x0000) +#define CLR_S_NO_READY_THREADS MAKE_HRESULT(SEVERITY_SUCCESS, 0x0300, 0x0000) +#define CLR_S_NO_THREADS MAKE_HRESULT(SEVERITY_SUCCESS, 0x0400, 0x0000) +#define CLR_S_RESTART_EXECUTION MAKE_HRESULT(SEVERITY_SUCCESS, 0x0500, 0x0000) // clang-format off