Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.

Bug 1236615

Summary: [ppc64le] Divide and mod operations fail to wrap around on 64 bit integers
Product: Red Hat Enterprise Linux 7 Reporter: Richard W.M. Jones <rjones>
Component: ocamlAssignee: Richard W.M. Jones <rjones>
Status: CLOSED ERRATA QA Contact: Václav Kadlčík <vkadlcik>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.3CC: codonell, mcermak, vkadlcik
Target Milestone: rc   
Target Release: ---   
Hardware: ppc64le   
OS: Unspecified   
Whiteboard:
Fixed In Version: ocaml-4.01.0-22.6.el7 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-11-19 04:49:50 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
div.c none

Description Richard W.M. Jones 2015-06-29 14:40:16 UTC
Description of problem:

This error was found by running the test suite.  I have now enabled
the test suite (advisory only) in all Fedora builds, so we should
start seeing more of these kinds of detail problems.

Int64.rem (remainder) and Int64.div (divide) functions on 64 bit
integers do not work.

Save the following snippet of code as `test.ml':

------
open Printf
let () =
  let i = Int64.min_int in
  printf "i = Int64.min_int = %Ld\n" i;
  let j = Int64.of_int (-1) in
  printf "j = Int64.of_int -1 = %Ld\n" j;
  printf "Int64.rem i j = %Ld (expecting 0)\n" (Int64.rem i j);
  printf "Int64.div i j = %Ld (expecting min_int)\n" (Int64.div i j)
------

and compile it using:

ocamlopt.opt test.ml -o test

On x86-64 (no error):

$ ./test
i = Int64.min_int = -9223372036854775808
j = Int64.of_int -1 = -1
Int64.rem i j = 0 (expecting 0)
Int64.div i j = -9223372036854775808 (expecting min_int)

On ppc64le:

i = Int64.min_int = -9223372036854775808
j = Int64.of_int -1 = -1
Int64.rem i j = 9223372036854775807 (expecting 0)
Int64.div i j = -1 (expecting min_int)

Version-Release number of selected component (if applicable):

I'm actually testing this on Fedora, but since the Fedora and
RHEL ppc64le code generators are substantially identical, I
expect the same problem to happen there.

ocaml-4.01.0-24.fc21.ppc64le

It also happens with the fedora-ocaml repository which is where
we get Fedora and RHEL versions of OCaml from.
https://git.fedorahosted.org/git/fedora-ocaml.git

How reproducible:

100% - see above.

Comment 1 Richard W.M. Jones 2015-06-29 14:42:03 UTC
The bytecode compiler (ocamlc) works.

Comment 3 Richard W.M. Jones 2015-06-29 15:07:28 UTC
Created attachment 1044384 [details]
div.c

Attached is what I think would be an equivalent C program.

It gives the same results as the (x86-64) OCaml program when
I use gcc -O3:

$ gcc -O3 -Wall div.c -o div
$ ./div
i = INT64_MIN = -9223372036854775808
j = -1 = -1
rem i j = 0
div i j = -9223372036854775808

Strangely, on x86-64, with gcc -O0 I get this:

$ gcc -Wall div.c -o div
$ ./div
i = INT64_MIN = -9223372036854775808
j = -1 = -1
Floating point exception

On ppc64le, with gcc -O0, I get:

i = INT64_MIN = -9223372036854775808
j = -1 = -1
rem i j = 9223372036854775807
div i j = -1

Comment 4 Richard W.M. Jones 2015-06-29 16:27:38 UTC
Carlos O'Donell points on that the code in comment 3 invokes
signed integer overflow (in the division) and so the behaviour
is undefined.

Comment 5 Carlos O'Donell 2015-06-29 16:31:27 UTC
(In reply to Richard W.M. Jones from comment #4)
> Carlos O'Donell points on that the code in comment 3 invokes
> signed integer overflow (in the division) and so the behaviour
> is undefined.

The result of the division is "(-1)(INT64_MIN)" and is unrepresentable as a signed 64-bit two's compliment value. The signed integer overflow results in undefined behaviour both in the C program, and possibly in the Ocaml program (though there you would have to look at the language standard to see what it says). Even if Ocaml allowed it the result is unrepresentable in a type of the same width of storage e.g. 64-bits. The test case would be valid only if you used larger types e.g. 128-bits. The undefined behaviour allows the compiler to do anything it wants with the division and remainder operations, so you see a variety of results. It is my opinion that the highest quality result is that for x86_64 at -O0 which yields SIGFPE as it should since the result is unrepresentable.

The Ocaml test case is IMO likely invalid and should be fixed upstream.

Comment 6 Richard W.M. Jones 2015-06-29 16:42:00 UTC
The OCaml test is actually testing the wraparound case, because
int64 is supposed to wrap there.

Int64.min_int ÷ -1 -> Int64.max_int + 1 -> Int64.min_int
                                     wraparound

Comment 7 Richard W.M. Jones 2015-06-29 16:57:51 UTC
Extract from -dlambda output:

               (apply (field 1 (global Printf!))
                 [0:
                  [11:
                   "Int64.rem i j = "
                   [7: 0a 0a 0a [11: " (expecting 0)\n" 0a]]]
                  "Int64.rem i j = %Ld (expecting 0)\n"]
                 (Int64.mod i/1008 j/1009))
               (apply (field 1 (global Printf!))
                 [0:
                  [11:
                   "Int64.div i j = "
                   [7: 0a 0a 0a [11: " (expecting min_int)\n" 0a]]]
                  "Int64.div i j = %Ld (expecting min_int)\n"]
                 (Int64.div i/1008 j/1009)))))))

and from -dclambda output:

         (apply
           (apply* camlPrintf__fprintf_1025 
             (field 23 (global camlPervasives!))
             "camlTest__18"=block(0,"camlTest__16"=block(11,"camlTest__12"="Int64.rem i j = ","camlTest__15"=block(7,0a,0a,0a,"camlTest__14"=block(11,"camlTest__13"=" (expecting 0)\n",0a))),"camlTest__17"="Int64.rem i j = %Ld (expecting 0)\n"))
           "camlTest__19"=9223372036854775807L)
         (apply
           (apply* camlPrintf__fprintf_1025 
             (field 23 (global camlPervasives!))
             "camlTest__26"=block(0,"camlTest__24"=block(11,"camlTest__20"="Int64.div i j = ","camlTest__23"=block(7,0a,0a,0a,"camlTest__22"=block(11,"camlTest__21"=" (expecting min_int)\n",0a))),"camlTest__25"="Int64.div i j = %Ld (expecting min_int)\n"))
           "camlTest__7"=-1L)))

This shows that some kind of constant folding is happening
between these two stages.

Comment 8 Richard W.M. Jones 2015-06-29 18:17:13 UTC
Answer from upstream is to set:
let division_crashes_on_overflow = true                                         

See: https://groups.google.com/d/msg/ocaml-aggregation-list/WoT1x7q3EVY/6X5bjxgFv9YJ

Comment 9 Richard W.M. Jones 2015-06-29 20:54:03 UTC
This is a fix for the problem in Fedora:

https://git.fedorahosted.org/cgit/fedora-ocaml.git/patch/?id=cf026cf66315609afe8f76272e493259bade255f

I will leave this bug open because we need to fix it in RHEL too.

Comment 13 errata-xmlrpc 2015-11-19 04:49:50 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHBA-2015-2185.html