10.1B Changes Integer Math Wrapping Behavior

November 22, 2007 · Filed Under Development, Reliability 

An encryption component built into one of Solvepoint’s products came to our attention in a regression test on 10.1B. The root cause was a change in integer math wrapping behavior. Notice, I said “change”. I did not say “improvement”.

Some background, first. In most major computing languages integers wrap when an operation overflows the maximum allowed integer.

  • In C# int i = int.MaxValue + 1; wraps.
  • In ANSI C unsigned integers wrap.
  • In Java integers wrap.

Integer wrapping behavior is an embedded, predictable and necessary part of many applications including a number of encryption algorithms, communications stacks, and data verification algorithms.

What about Progress applications? Well,…

All versions of Progress prior to 10.1B wrapped integers.

With the coming of 64-bit integers someone at Progress realized that it was possible to do 32-bit arithmetic in 64-bits and actually know whether the result went beyond the maximum (or minimum) integer. But just because something could be done doesn’t mean it should be done. So even though the Decimal data-type exists as an easy alternative to those wanting to avoid classic integer behavior, Progress changed integer math in 10.1B to throw an error instead of wrapping. If you’re incredulous, see Solution ID P119716.

In 10.1B 32-bit integer wraps throw an error “Value integer too large to fit in INTEGER datatype. (13682)“. Be prepared for some code written long ago to break.

If we multiply an integer less than the maximum 32-bit integer by a multiplicand that will result in a value greater than the maximum 32-bit integer, we can see the issue played out. In the following example we will use 1234567891 (a large easy to remember number less than max 32-bit int, +2,147,483,647) and multiply it by 10. In Pre 10.1B the result is -539222978, but as of 10.1B it returns an error.

Difference between 32 bit signed integers in OpenEdge 10.1B

Looking at the binary underneath this, see where 10.1B detects the overflow within 64-bits and throws the 32-bit exception #13682:

How OpenEdge 10.1B detects overflow

But can we now declare all Progress integer math safe? Not really. Since 64-bit integers in 10.1B are as blind to the >64 bits as 32-bit integers were to the >32 bits before 10.1B, 64-bit integers in 10.1B wrap around the way 32-bit integers did before 10.1B. (read that sentence several time if need be ) To help you understand why, Progress says “Checking for 64bit overflow would be too expensive. To do it would require putting everything in 128 bits to do calculations and then to copy it all back, since >64bits are required to do 64bit overflow checking. This would cause all arithmetic in the 4gl to grind to a halt. There are therefore no plans to do anything about this.”

So you’ve been warned. When this bites you’ll be able to say, “Darn!, and I read something about that somewhere!”

PS: And yes, for all the hard-core C jocks, signed integer wrapping is implementation dependent, not guaranteed to demonstrate modulus behavior, but usually wraps. Use of a signed integers rather than unsigned integers when classic integer wrapping is needed in C is a no-no.

Comments

Leave a Reply

You must be logged in to post a comment.