Skip to content

Commit

Permalink
Merge pull request #48 from tosca-lang/fix-formatinteger-overflow
Browse files Browse the repository at this point in the history
Fix formatinteger overflow
  • Loading branch information
yahelnachum committed Feb 11, 2019
2 parents 2b9c5cc + eea378f commit 017dd88
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 6 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ Download [atom](https://atom.io), install it then start Atom. Go to Preferences

Changes
=======
* Verxion 1.0.8 - add support for import-path directories, add support for line comments and block comments in term reader, fixes various memory leaks. Fixes issues 41, 43, 44, 45.
* Version 1.0.9 - Fix overflows in FormatInteger.
* Version 1.0.8 - add support for import-path directories, add support for line comments and block comments in term reader, fixes various memory leaks. Fixes issues 41, 43, 44, 45.
* Version 1.0.7 - fixes non-thread-safe issue with ref counting in C++ backend.
* Version 1.0.6 - fixes to make Tosca compile after clean pull from github
* Version 1.0.5 - gcc 4.8 support for C++ backend.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION=1.0.8
VERSION=1.0.9
26 changes: 26 additions & 0 deletions src/std/num.tsc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@
*/
import std::core

// --- integer max and min declarations

/* @return Internal number to represent integer max based on double's
precision (mantissa is 53 bits). Note that integer is
language specific. In C++ the integer primitive is long
long (64 bits). In Java the integer primitive is int
(32 bits). */
@Extern func GetDefine_INTEGER_MAX_DBL_PRECISION() -> Numeric

/* @return Internal number to represent integer min based on double's
precision (mantissa is 53 bits). Note that integer is
language specific. In C++ the integer primitive is long
long (64 bits). In Java the integer primitive is int
(32 bits). */
@Extern func GetDefine_INTEGER_MIN_DBL_PRECISION() -> Numeric

/* @return clip the number given to the internal integer max or min
if it is outside of that interval, otherwise return the
original number */
@Extern func ClipToMaxOrMin(Numeric) -> Numeric

/* @return TRUE if and only if the the number given is within the
internal integer min to max interval */
@Extern func IsWithinIntegerPrecision(Numeric) -> Bool


@Extern func Plus(Numeric, Numeric) -> Numeric
@Extern func Minus(Numeric, Numeric) -> Numeric
@Extern func Times(Numeric, Numeric) -> Numeric
Expand Down
68 changes: 66 additions & 2 deletions targets/cpp/std/src/std/num-extern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,69 @@

using namespace tosca;

// integer max and min definitions

/* @brief Internal number to represent integer max based on double's
precision (mantissa is 53 bits). Note that integer is
language specific. In C++ the integer primitive is long
long (64 bits). In Java the integer primitive is int
(32 bits). */
#define INTEGER_MAX_DBL_PRECISION (1LL<<53)

/* @brief Internal number to represent integer min based on double's
precision (mantissa is 53 bits). Note that integer is
language specific. In C++ the integer primitive is long
long (64 bits). In Java the integer primitive is int
(32 bits). */
#define INTEGER_MIN_DBL_PRECISION ((1LL<<53) * -1)

DoubleTerm& GetDefine_INTEGER_MAX_DBL_PRECISION(Context& ctx)
{
return newDoubleTerm(ctx, INTEGER_MAX_DBL_PRECISION);
}

DoubleTerm& GetDefine_INTEGER_MIN_DBL_PRECISION(Context& ctx)
{
return newDoubleTerm(ctx, INTEGER_MIN_DBL_PRECISION);
}

DoubleTerm& ClipToMaxOrMin(Context& ctx, DoubleTerm& dTerm)
{
DoubleTerm result;
double d = dTerm.Unbox();
if (d > INTEGER_MAX_DBL_PRECISION)
{
dTerm.Release();
return GetDefine_INTEGER_MAX_DBL_PRECISION(ctx);
}
else if (d < INTEGER_MIN_DBL_PRECISION)
{
dTerm.Release();
return GetDefine_INTEGER_MIN_DBL_PRECISION(ctx);
}
else
{
dTerm.Release();
return newDoubleTerm(ctx, d);
}
}

Bool& IsWithinIntegerPrecision(Context& ctx, DoubleTerm& dTerm)
{
double d = dTerm.Unbox();
if (d > INTEGER_MAX_DBL_PRECISION ||
d < INTEGER_MIN_DBL_PRECISION)
{
dTerm.Release();
return newFALSE(ctx);
}
else
{
dTerm.Release();
return newTRUE(ctx);
}
}

DoubleTerm& Plus(Context& ctx, DoubleTerm& left, DoubleTerm& right)
{
DoubleTerm& result = newDoubleTerm(ctx, left.Unbox() + right.Unbox());
Expand Down Expand Up @@ -82,8 +145,9 @@ StringTerm& FormatNumber(Context& ctx, DoubleTerm& num)

StringTerm& FormatInteger(Context& ctx, DoubleTerm& num)
{
long long unum = (long long) num.Unbox();
num.Release();
DoubleTerm& unumTerm = ClipToMaxOrMin(ctx, num);
long long unum = (long long) unumTerm.Unbox();
unumTerm.Release();
char* str = (char*) alloca((size_t) 32);
snprintf(str, (size_t) 31, "%lld", unum);
return newStringTerm(ctx, str);
Expand Down
5 changes: 5 additions & 0 deletions targets/cpp/std/src/std/num-extern_sigs.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
#include "ts.h"
#include "core_types.h"

tosca::DoubleTerm& GetDefine_INTEGER_MAX_DBL_PRECISION(tosca::Context& ctx);
tosca::DoubleTerm& GetDefine_INTEGER_MIN_DBL_PRECISION(tosca::Context& ctx);
tosca::DoubleTerm& ClipToMaxOrMin(tosca::Context& ctx, tosca::DoubleTerm& dTerm);
Bool& IsWithinIntegerPrecision(tosca::Context& ctx, tosca::DoubleTerm& dTerm);

tosca::DoubleTerm& Plus(tosca::Context& ctx, tosca::DoubleTerm& left, tosca::DoubleTerm& right);
tosca::DoubleTerm& Minus(tosca::Context& ctx, tosca::DoubleTerm& left, tosca::DoubleTerm& right);
tosca::DoubleTerm& Times(tosca::Context& ctx, tosca::DoubleTerm& left, tosca::DoubleTerm& right);
Expand Down
67 changes: 65 additions & 2 deletions targets/java/runtime/org/transscript/compiler/std/NumExtern.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,68 @@

public class NumExtern
{
/* @brief Internal number to represent integer max based on double's
precision (mantissa is 53 bits). Note that integer is
language specific. In C++ the integer primitive is long
long (64 bits). In Java the integer primitive is int
(32 bits). */
final private static double INTEGER_MAX_DBL_PRECISION = Integer.MAX_VALUE;

/* @brief Internal number to represent integer min based on double's
precision (mantissa is 53 bits). Note that integer is
language specific. In C++ the integer primitive is long
long (64 bits). In Java the integer primitive is int
(32 bits). */
final private static double INTEGER_MIN_DBL_PRECISION = Integer.MIN_VALUE;

final public static DoubleTerm GetDefine_INTEGER_MAX_DBL_PRECISION(Context context)
{
return DoubleTerm.doubleTerm(INTEGER_MAX_DBL_PRECISION);
}

final public static DoubleTerm GetDefine_INTEGER_MIN_DBL_PRECISION(Context context)
{
return DoubleTerm.doubleTerm(INTEGER_MIN_DBL_PRECISION);
}

final public static DoubleTerm ClipToMaxOrMin(Context context, DoubleTerm dTerm)
{
DoubleTerm result;
DoubleTerm edTerm = dTerm.eval(context);
double d = edTerm.unbox();
if (d > INTEGER_MAX_DBL_PRECISION)
{
result = GetDefine_INTEGER_MAX_DBL_PRECISION(context);
}
else if (d < INTEGER_MIN_DBL_PRECISION)
{
result = GetDefine_INTEGER_MIN_DBL_PRECISION(context);
}
else
{
result = DoubleTerm.doubleTerm(d);
}
edTerm.release();
return result;
}

public static Bool IsWithinIntegerPrecision(Context context, DoubleTerm dTerm)
{
Bool result;
DoubleTerm edTerm = dTerm.eval(context);
double d = edTerm.unbox();
if (d > INTEGER_MAX_DBL_PRECISION ||
d < INTEGER_MIN_DBL_PRECISION)
{
result = Core.FALSE(context);
}
else
{
result = Core.TRUE(context);
}
edTerm.release();
return result;
}

final public static DoubleTerm Plus(Context context, DoubleTerm left, DoubleTerm right)
{
Expand Down Expand Up @@ -85,8 +147,9 @@ public static StringTerm FormatDecimal(Context context, DoubleTerm value_1396)

public static StringTerm FormatInteger(Context context, DoubleTerm num)
{
StringTerm result = stringTerm(Integer.toString((int) num.unbox()));
num.release();
DoubleTerm unumTerm = ClipToMaxOrMin(context, num);
StringTerm result = stringTerm(Integer.toString((int) unumTerm.unbox()));
unumTerm.release();
return result;
}

Expand Down

0 comments on commit 017dd88

Please sign in to comment.