Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #69548 > unrolled thread
| Started by | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| First post | 2019-11-04 20:48 +0100 |
| Last post | 2020-02-26 02:22 +0000 |
| Articles | 20 on this page of 219 — 25 participants |
Back to article view | Back to comp.lang.c++
two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-04 20:48 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-04 21:19 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-04 14:39 -0800
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-05 10:31 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-05 11:23 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-05 15:43 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-05 16:58 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-05 21:45 +0200
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-06 13:33 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 13:51 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-06 14:37 +0100
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-06 15:38 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 15:53 +0100
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-11-06 10:06 -0500
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-11-06 17:00 +0100
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-06 17:47 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 17:54 +0100
Re: two's complement idea Bo Persson <bo@bo-persson.se> - 2019-11-06 20:00 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 20:13 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-06 20:44 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-06 20:36 +0100
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-06 22:54 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-07 00:52 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-06 17:54 +0200
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-06 18:15 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 18:33 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-06 10:55 -0800
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 20:15 +0100
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-06 20:53 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-06 22:25 +0200
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-06 23:05 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-07 10:23 +0200
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-06 22:20 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-06 22:12 +0200
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-09 06:24 -0800
Re: two's complement idea Siri Cruise <chine.bleu@yahoo.com> - 2019-11-09 07:14 -0700
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-10 11:52 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-10 16:31 +0200
Re: two's complement idea Manfred <noname@invalid.add> - 2019-11-10 19:02 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-11 12:08 +0200
Re: two's complement idea scott@slp53.sl.home (Scott Lurndal) - 2019-11-11 13:59 +0000
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2019-11-11 17:09 +0200
Re: two's complement idea Richard Damon <Richard@Damon-Family.org> - 2019-11-18 07:40 -0500
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 12:27 -0800
Re: two's complement idea cdalten@gmail.com - 2020-01-24 05:39 -0800
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-24 17:53 +0200
Re: two's complement idea Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-24 17:31 +0000
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-05 21:48 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 07:08 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-06 09:30 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-06 09:57 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-05 09:02 -0800
Re: two's complement idea scott@slp53.sl.home (Scott Lurndal) - 2019-11-05 17:15 +0000
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-05 10:19 -0800
Re: two's complement idea Manfred <noname@invalid.add> - 2019-11-05 19:31 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-05 11:55 -0800
Re: two's complement idea Manfred <noname@add.invalid> - 2019-11-05 22:48 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-05 15:49 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-09 06:13 -0800
Re: two's complement idea Manfred <noname@invalid.add> - 2019-11-10 18:37 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-05 23:14 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-05 23:00 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-06 05:26 -0800
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-06 21:50 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-08 02:01 -0800
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-08 14:03 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-08 12:08 -0800
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-10 13:17 +0100
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-11-10 14:37 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-10 17:08 +0100
Re: two's complement idea Manfred <noname@invalid.add> - 2019-11-10 18:34 +0100
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2019-11-11 07:48 +1300
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-10 21:31 +0100
Re: two's complement idea Bo Persson <bo@bo-persson.se> - 2019-11-04 23:55 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-05 10:32 +0100
Re: two's complement idea Siri Cruise <chine.bleu@yahoo.com> - 2019-11-04 19:55 -0700
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-11-05 05:52 +0100
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2019-11-05 18:17 +1300
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-09 05:55 -0800
Re: two's complement idea Siri Cruise <chine.bleu@yahoo.com> - 2019-11-09 06:33 -0700
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-09 07:46 -0800
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-09 06:46 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 12:19 -0800
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-11-29 00:14 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-29 09:15 +0100
Re: two's complement idea Bo Persson <bo@bo-persson.se> - 2019-11-29 10:58 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2019-11-29 12:49 +0100
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-12-07 07:53 -0800
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-12-07 08:22 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-10 20:44 -0800
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-10 23:44 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-14 07:08 -0800
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-14 08:42 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-21 02:09 -0800
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-21 05:14 -0800
Re: two's complement idea Daniel <danielaparker@gmail.com> - 2020-01-21 13:08 -0800
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-22 00:07 -0500
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-21 23:21 -0800
Re: two's complement idea Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-01-22 01:51 -0800
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-22 11:28 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-22 11:52 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-22 04:47 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-04-02 07:19 -0700
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-04-02 08:07 -0700
Re: two's complement idea boltar@nowhere.org - 2020-01-21 16:44 +0000
Re: two's complement idea Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-21 20:01 +0000
Re: two's complement idea boltar@nowhere.org - 2020-01-22 11:26 +0000
Re: two's complement idea Christian Gollwitzer <auriocus@gmx.de> - 2020-01-22 20:04 +0100
Re: two's complement idea Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-01-22 11:30 -0800
Re: two's complement idea Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2020-01-22 19:57 +0000
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-23 10:03 +1300
Re: two's complement idea boltar@nowhere.org - 2020-01-23 09:24 +0000
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-24 07:29 +1300
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-23 10:03 +1300
Re: two's complement idea "Fred. Zwarts" <F.Zwarts@KVI.nl> - 2020-01-23 10:09 +0100
Re: two's complement idea boltar@nowhere.org - 2020-01-23 09:29 +0000
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-24 01:08 +0000
Re: two's complement idea boltar@nowhere.org - 2020-01-24 12:27 +0000
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-24 01:06 +0000
Re: two's complement idea Bo Persson <bo@bo-persson.se> - 2020-01-24 10:07 +0100
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-24 11:36 +0200
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-24 17:34 -0800
Re: two's complement idea Siri Cruise <chine.bleu@yahoo.com> - 2020-01-24 17:57 -0800
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-24 12:19 +0000
Re: two's complement idea Bo Persson <bo@bo-persson.se> - 2020-01-24 14:19 +0100
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-24 14:11 +0000
Re: two's complement idea Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-24 17:26 +0000
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-24 17:35 +0000
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-24 22:27 +0200
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-24 23:21 -0500
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-25 11:06 +1300
Re: two's complement idea Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-24 22:12 +0000
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-24 23:24 -0500
Re: two's complement idea Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-25 09:04 +0000
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-25 04:15 -0800
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-25 19:55 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-25 00:05 +0100
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-25 01:19 +0000
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-25 19:50 +1300
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-25 11:57 +0000
Re: two's complement idea Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2020-01-25 13:42 +0000
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-25 14:58 +0000
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-26 07:58 +1300
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-25 20:34 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-25 12:41 -0800
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-26 16:08 +0200
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-27 02:20 -0800
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-27 15:03 +0200
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-15 06:44 -0800
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-03-06 10:18 +0200
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-04-02 07:05 -0700
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-04-02 20:03 +0300
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-04-04 12:37 -0700
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-26 07:45 +1300
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-25 19:56 +0000
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-26 09:49 +1300
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-25 21:33 +0000
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-26 11:00 +1300
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-25 22:23 +0000
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-26 11:46 +1300
Re: two's complement idea Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-26 10:55 +0200
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2020-01-26 03:47 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-27 01:28 -0800
Re: two's complement idea Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-25 22:22 +0000
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-25 18:24 -0500
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-26 12:54 +0100
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-26 12:44 +0000
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-26 14:58 +0100
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-26 14:53 +0000
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-26 19:10 +0100
Re: two's complement idea Robert Wessel <robertwessel2@yahoo.com> - 2020-01-26 13:20 -0600
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-26 20:51 +0000
Re: two's complement idea Robert Wessel <robertwessel2@yahoo.com> - 2020-01-26 21:02 -0600
Re: two's complement idea Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-01-26 19:06 -0800
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-27 18:50 +0000
Re: two's complement idea Robert Wessel <robertwessel2@yahoo.com> - 2020-01-27 14:18 -0600
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-27 22:13 +0100
Re: two's complement idea Bart <bc@freeuk.com> - 2020-01-27 21:38 +0000
Re: two's complement idea Robert Wessel <robertwessel2@yahoo.com> - 2020-01-27 19:37 -0600
Re: two's complement idea Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-01-27 19:15 -0800
Re: two's complement idea "Fred. Zwarts" <F.Zwarts@KVI.nl> - 2020-01-28 11:45 +0100
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-27 16:31 +1300
Re: two's complement idea Manfred <noname@add.invalid> - 2020-01-26 18:50 +0100
Re: two's complement idea Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-26 18:57 +0000
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-26 20:46 +0100
Re: two's complement idea Robert Wessel <robertwessel2@yahoo.com> - 2020-01-26 13:14 -0600
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-26 22:15 +0100
Re: two's complement idea Robert Wessel <robertwessel2@yahoo.com> - 2020-01-27 21:06 -0600
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-28 13:08 +0100
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-27 01:50 -0800
Re: two's complement idea Ian Collins <ian-news@hotmail.com> - 2020-01-27 08:21 +1300
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-25 20:14 +0100
Re: two's complement idea David Brown <david.brown@hesbynett.no> - 2020-01-25 20:12 +0100
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-27 07:48 -0800
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2020-02-18 18:46 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-09 17:03 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-05 06:56 +0100
Re: two's complement idea Christian Gollwitzer <auriocus@gmx.de> - 2019-11-05 08:24 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2019-11-05 08:35 +0100
Re: two's complement idea Öö Tiib <ootiib@hot.ee> - 2019-11-04 23:36 -0800
Re: two's complement idea James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-11-05 09:19 -0500
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-22 08:32 +0100
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2020-01-22 09:23 +0100
Re: two's complement idea Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-22 14:20 +0100
Re: two's complement idea Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2020-01-22 13:37 +0000
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-27 01:17 -0800
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2020-01-27 12:35 +0100
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-15 05:56 -0800
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2020-02-16 09:17 +0100
Re: two's complement idea Richard Damon <Richard@Damon-Family.org> - 2020-02-21 19:35 -0500
Re: two's complement idea "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2020-02-22 07:01 +0100
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-24 08:22 -0800
Re: two's complement idea cross@spitfire.i.gajendra.net (Dan Cross) - 2020-02-24 03:12 +0000
Re: two's complement idea cdalten@gmail.com - 2020-02-24 05:53 -0800
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-25 07:56 -0800
Re: two's complement idea cross@spitfire.i.gajendra.net (Dan Cross) - 2020-02-25 22:00 +0000
Re: two's complement idea Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-25 16:14 -0800
Re: two's complement idea cdalten@gmail.com - 2020-02-25 18:18 -0800
Re: two's complement idea cross@spitfire.i.gajendra.net (Dan Cross) - 2020-02-26 02:22 +0000
Page 2 of 11 — ← Prev page 1 [2] 3 4 … 11 Next page →
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-11-06 20:36 +0100 |
| Message-ID | <qpv7bt$v46$1@dont-email.me> |
| In reply to | #69594 |
On 06/11/2019 15:38, Manfred wrote:
> On 11/6/2019 2:37 PM, David Brown wrote:
>> On 06/11/2019 13:33, Manfred wrote:
>>> On 11/5/2019 8:45 PM, Paavo Helde wrote:
>>>> On 5.11.2019 17:58, Bonita Montero wrote:
>>>>>
>>>>> With the same reasoning you could say that unsigneds might never
>>>>> wrap; but in fact they're specified to wrap.
>>>>
>>>> In retrospect, this (wrapping unsigneds) looks like a major design
>>>> mistake.
>>>
>>> No, it isn't.
>>>
>>>>
>>>> IMO, wrapping integers (signed or unsigned) are an example of
>>>> "optimization which nobody asked for", and they are there basically
>>>> only because the hardware happened to support such operations.
>>>>
>>>
>>> Look at the following code and see for yourself how efficient it is to
>>> check for integer overflow if unsigned integers do wrap.
>>> Achieving the same would be much more verbose (and less efficient) if
>>> unsigned overflow were not defined behavior.
>>>
>>> (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1969.htm)
>>>
>>> char* make_pathname (const char *dir, const char *fname, const char
>>> *ext)
>>> {
>>> size_t dirlen = strlen (dir);
>>> size_t filelen = strlen (fname);
>>> size_t extlen = strlen (ext);
>>>
>>> size_t pathlen = dirlen;
>>>
>>> // detect and handle integer wrapping
>>> if ( (pathlen += filelen) < filelen
>>> || (pathlen += extlen) < extlen
>>> || (pathlen += 3) < 3)
>>> return 0;
>>
>> That is just silly, in all sorts of ways.
>
> You realize that this comes from the glibc maintainers, don't you?
No. But that doesn't change my opinion - at least not much. It makes a
bit more sense if it has to be portable to DOS, for example, with 16-bit
size_t.
> You can say they wrote silly code for this example (I don't), but I
> doubt there are many more knowledgeable people about this kind of matter
> than them.
>
> Moreover, I took this as an example of detection of integer overflow.
> The fact that it happens to be about pathname strings is irrelevant to
> this discussion.
It is, IMHO, a fine example of when overflow should not be issue - and
that defined overflow behaviour is a lot less useful than many people think.
(I still agree that occasionally it is useful.)
>
>>
>> First, decide if the function is an "internal" function where you can
>> trust the parameters, and have undefined behaviour if assumptions don't
>> hold, or an "external" function where you have to check the validity of
>> the parameters.
>
> This example was written about code safety, so yes, I believe it is
> pretty clear the assumption is that strings come from an external source.
> Obviously this applies to string /contents/; the pointer themselves can
> only be internal to the program (can't they?), so no need to check for
> null pointer.
I don't know the circumstances for this function, so I can't answer
that. But if it is an externally accessible function, I think checks
for null pointers would make sense.
> On the other hand, contents of the string is checked by ensuring that
> the result of strlen and their combination is valid. This is ensured
> /exactly/ by making use of unsigned wrapping behavior.
>
The code is going out of its way to check something that is almost
impossible to occur, even with malicious intentions - while ignoring
problems that could easily occur even by accident.
>>
>> If it is internal, you know the lengths of the passed strings will not
>> sum to more than 4G - or you don't care if someone does something
>> ridiculous. (And on most modern systems, size_t is 64-bit - overflowing
>> here would require 16 EB ram for storing the strings.)
>>
>> If it is external, the checking is too little - if you have char*
>> pointers from an unknown source, you should be wary about running
>> strlen() on them because you don't know if it will actually end with a 0
>> in a reasonable limit.
>
> This code handles C strings, so there is no way to check for their
> length other than running strlen.
size_t limited_strlen(const char* s, size_t n) {
const char* p = memchr(s, 0, n);
if (!p) return (size_t) -1; // Indicate bad string
return p - s;
}
> The fact that you seem to miss is that it is exactly thanks to the check
> that you call "silly" that it is ensured that they "actually end with a
> 0 in a reasonable limit".
The checks don't do that. If the three parameters pointed to strings
adding up to 4 GB - 1 characters in total, by what stretch of the
imagination is that "in a reasonable limit" ?
>
> We could argue about what happens with /read/ access to a
> non-0-terminated string, but I would simply assume that the strings are
> 0 terminated, since the function is going to be called by some other
> part of the program that can take care that there is a 0 at the end of
> the buffer.
Failing to 0 terminate a character sequence that is intended to be a
string is not an uncommon bug.
> What is not guaranteed is that the strings actually contain
> pathnames, and don't contain very long malicious text instead (e.g. they
> could come from stdin).
You need text sequences totalling more than 4 GB to cause a problem (and
that's on older 32-bit size_t systems). Since the user program can't
have as much as 4 GB of data space, you'd need not only huge malicious
texts, but you'd also need at least two of the three parameters to overlap.
> That risk is avoided by the code you call silly.
> So, no there is not too little checking.
>
>>
>>
>> You only need to check for overflow if it is possible for the
>> calculations to overflow. If the operands are too small to cause an
>> overflow, there will not be an overflow.
>>
>> And until you are talking about large integers for cryptography or that
>> sort of thing, adding up realistic numbers will not overflow a 64-bit
>> type.
>
> In fact cryptography is another example where unsigned wrap is useful,
> but it would be much more complex (and off topic) to draw an example of
> this (not that I claim to be an expert in this area)
Yes, I agree. As I said, sometimes unsigned wrap is useful. But not in
this example.
>
> And no, just assuming that "adding up realistic numbers will not
> overflow a 64-bit type" is not what safe code is about.
Safe coding is never about assuming anything. But safe coding involves
looking at what values can occur (intentionally and unintentionally),
and making checks /only/ when you need checks. It involves /thinking/,
rather than making checks in the blind "just in case". And when you
have 64-bit types, there are few non-specialist occasions when your
values can overflow with simple addition. If there is a risk of their
being an overflow, then you probably have not sanity checked the values
coming in.
>
>>
>> So /if/ you have an old 32-bit size_t system, and /if/ you have
>> maliciously crafted parameters that point to huge strings (and you'll
>> have to make them point within the same string - you don't get over 4 GB
>> user memory address space with 32-bit size_t), then you can do your
>> adding up using 64-bit types and you get zero risk of overflow.
>>
>>
>> uint_least64_t dirlen = strlen (dir);
>> uint_least64_t filelen = strlen (fname);
>> uint_least64_t extlen = strlen (ext);
>>
>> uint_least64_t pathlen = dirlen + filelen + extlen;
>>
>> if (big_size_t > MAX_SANE_PATHLENGTH) return 0;
>
> You realize that this code is less efficient than the original one,
> don't you?
You realise that it is /more/ efficient on any 64-bit system? And that
on 32-bit systems it is at most marginally less efficient, but might be
more efficient (by avoiding branches)? And that this code does
something /useful/ by checking for a sensible maximum pathlength? And
that any few instruction cycles lost here are negligible compared to the
hundreds that are needed for copying even a small path string?
> And what would be the correct value for MAX_SANE_PATHLENGTH? Are you
> aware of the trouble that has been caused by Windows MAX_PATH?
You'd pick a big value for it - but a lot less than 4G. Most
filesystems limit file names to 255 bytes. What would you say is a
maximum depth of directories before it is clear that you have thoroughly
screwed up somewhere - maybe 1000? So pick MAX_SANE_PATHLENGTH at 256K
on 32-bit systems, and 16M on 64-bit systems. People with more
knowledge of the target system in question can pick better values.
POSIX used to have a limit of 4096, which was okay in the old days but
got a bit limiting. Windows is limited to 32K now, which seems to be
fine - the old limit was 260 characters which is clearly too small.
>
> The example I posted achieves the same level of safety, using less
> resources, and allowing for the maximum string length that the system
> can /safely/ handle (don't miss the check after malloc). What more do
> you want?
See what I wrote above.
>
>>
>>
>> There are times when unsigned wrapping overflow is useful. This is not
>> one of them.
>>
>
> I suggest you read the code again (and its source - it is instructive)
I did.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2019-11-06 22:54 +0100 |
| Message-ID | <qpvfeu$3va$1@gioia.aioe.org> |
| In reply to | #69607 |
On 11/6/2019 8:36 PM, David Brown wrote:
> On 06/11/2019 15:38, Manfred wrote:
>> On 11/6/2019 2:37 PM, David Brown wrote:
>>> On 06/11/2019 13:33, Manfred wrote:
>>>> On 11/5/2019 8:45 PM, Paavo Helde wrote:
>>>>> On 5.11.2019 17:58, Bonita Montero wrote:
>>>>>>
>>>>>> With the same reasoning you could say that unsigneds might never
>>>>>> wrap; but in fact they're specified to wrap.
>>>>>
>>>>> In retrospect, this (wrapping unsigneds) looks like a major design
>>>>> mistake.
>>>>
>>>> No, it isn't.
>>>>
>>>>>
>>>>> IMO, wrapping integers (signed or unsigned) are an example of
>>>>> "optimization which nobody asked for", and they are there basically
>>>>> only because the hardware happened to support such operations.
>>>>>
>>>>
>>>> Look at the following code and see for yourself how efficient it is to
>>>> check for integer overflow if unsigned integers do wrap.
>>>> Achieving the same would be much more verbose (and less efficient) if
>>>> unsigned overflow were not defined behavior.
>>>>
>>>> (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1969.htm)
>>>>
>>>> char* make_pathname (const char *dir, const char *fname, const char
>>>> *ext)
>>>> {
>>>> size_t dirlen = strlen (dir);
>>>> size_t filelen = strlen (fname);
>>>> size_t extlen = strlen (ext);
>>>>
>>>> size_t pathlen = dirlen;
>>>>
>>>> // detect and handle integer wrapping
>>>> if ( (pathlen += filelen) < filelen
>>>> || (pathlen += extlen) < extlen
>>>> || (pathlen += 3) < 3)
>>>> return 0;
>>>
>>> That is just silly, in all sorts of ways.
>>
>> You realize that this comes from the glibc maintainers, don't you?
>
> No. But that doesn't change my opinion - at least not much. It makes a
> bit more sense if it has to be portable to DOS, for example, with 16-bit
> size_t.
>
>> You can say they wrote silly code for this example (I don't), but I
>> doubt there are many more knowledgeable people about this kind of
>> matter than them.
[...]
>>>
>>> First, decide if the function is an "internal" function where you can
>>> trust the parameters, and have undefined behaviour if assumptions don't
>>> hold, or an "external" function where you have to check the validity of
>>> the parameters.
>>
>> This example was written about code safety, so yes, I believe it is
>> pretty clear the assumption is that strings come from an external source.
>> Obviously this applies to string /contents/; the pointer themselves
>> can only be internal to the program (can't they?), so no need to check
>> for null pointer.
>
> I don't know the circumstances for this function, so I can't answer
> that. But if it is an externally accessible function, I think checks
> for null pointers would make sense.
I think there is some misunderstanding about what we mean for "external"
here, and below.
This is an example of application code, in the context of code safety,
that may be written as part of the final program or as part of a
library. Either way, the pointers are in control of the programmer who
writes the program, and he does not want to pass null pointers here.
Yes, this may happen if there is a mistake somewhere in the program, but
this is not what code safety is about, it is about code correctness,
which is a somewhat different thing (although it is true that incorrect
code is almost certainly unsafe code as well).
It is for this reason that standard library functions do not check for
null on all pointers passed in, and I am sure you don't check for null
within every function you write.
Code safety as I understand it is about ensuring the program works as
expected with every kind of data input that is supplied to the /program/
- like through an I/O stream (kernel safety is a different matter of
course).
In other words, when you read from std::cin, a file or a socket, you
allocate a buffer and you know that its pointer is valid. When you reach
EOF you also know that the buffer is 0-terminated - you place a 0
yourself if the runtime does not do this for you.
What you don't know (you can't control it) is if the /contents/ between
the pointer address and the terminating 0 has a valid format, whether it
is too large or whatever, and that's what you need to ensure that your
program is robust against in order to be safe.
>
>> On the other hand, contents of the string is checked by ensuring that
>> the result of strlen and their combination is valid. This is ensured
>> /exactly/ by making use of unsigned wrapping behavior.
>>
>
> The code is going out of its way to check something that is almost
> impossible to occur, even with malicious intentions - while ignoring
> problems that could easily occur even by accident.
See above.
>
>>>
>>> If it is internal, you know the lengths of the passed strings will not
>>> sum to more than 4G - or you don't care if someone does something
>>> ridiculous. (And on most modern systems, size_t is 64-bit - overflowing
>>> here would require 16 EB ram for storing the strings.)
>>>
>>> If it is external, the checking is too little - if you have char*
>>> pointers from an unknown source, you should be wary about running
>>> strlen() on them because you don't know if it will actually end with a 0
>>> in a reasonable limit.
>>
>> This code handles C strings, so there is no way to check for their
>> length other than running strlen.
>
> size_t limited_strlen(const char* s, size_t n) {
> const char* p = memchr(s, 0, n);
> if (!p) return (size_t) -1; // Indicate bad string
> return p - s;
> }
Incidentally, this takes a (pointer, length) pair, which is not a C string.
But that's irrelevant, I explained above that the presence of the
terminating 0 can and needs to be ensured at the calling level.
>
>> The fact that you seem to miss is that it is exactly thanks to the
>> check that you call "silly" that it is ensured that they "actually end
>> with a 0 in a reasonable limit".
>
> The checks don't do that. If the three parameters pointed to strings
> adding up to 4 GB - 1 characters in total, by what stretch of the
> imagination is that "in a reasonable limit" ?
Define reasonable.
The checks ensure that the code will concat correctly whatever length
can be /safely/ handled by the system, and handle correctly excessive
lengths as well, thus covering the entire input domain. That's enough
for safety, with no need to introduce any dependency on an additional
and arbitrary parameter.
>
>>
>> We could argue about what happens with /read/ access to a
>> non-0-terminated string, but I would simply assume that the strings
>> are 0 terminated, since the function is going to be called by some
>> other part of the program that can take care that there is a 0 at the
>> end of the buffer.
>
> Failing to 0 terminate a character sequence that is intended to be a
> string is not an uncommon bug.
See above.
>
>> What is not guaranteed is that the strings actually contain pathnames,
>> and don't contain very long malicious text instead (e.g. they could
>> come from stdin).
>
> You need text sequences totalling more than 4 GB to cause a problem (and
> that's on older 32-bit size_t systems). Since the user program can't
> have as much as 4 GB of data space, you'd need not only huge malicious
> texts, but you'd also need at least two of the three parameters to overlap.
>
>
>> That risk is avoided by the code you call silly.
>> So, no there is not too little checking.
>>
>>>
>>>
>>> You only need to check for overflow if it is possible for the
>>> calculations to overflow. If the operands are too small to cause an
>>> overflow, there will not be an overflow.
>>>
Yes, keep "if the operands are too small" in mind, and see below.
[...]
>>
>>>
>>> So /if/ you have an old 32-bit size_t system, and /if/ you have
>>> maliciously crafted parameters that point to huge strings (and you'll
>>> have to make them point within the same string - you don't get over 4 GB
>>> user memory address space with 32-bit size_t), then you can do your
>>> adding up using 64-bit types and you get zero risk of overflow.
>>>
>>>
>>> uint_least64_t dirlen = strlen (dir);
>>> uint_least64_t filelen = strlen (fname);
>>> uint_least64_t extlen = strlen (ext);
>>>
>>> uint_least64_t pathlen = dirlen + filelen + extlen;
>>>
>>> if (big_size_t > MAX_SANE_PATHLENGTH) return 0;
>>
>> You realize that this code is less efficient than the original one,
>> don't you?
>
> You realise that it is /more/ efficient on any 64-bit system?
Watch out: you wrote this example for 32-bit, but on 64 bit it can fail
for large enough inputs:
// the following /can/ now silently overflow
>>> uint_least64_t pathlen = dirlen + filelen + extlen;
>>>
>>> if (big_size_t > MAX_SANE_PATHLENGTH) return 0;
That is, on 64-bit it becomes unsafe.
And that
> on 32-bit systems it is at most marginally less efficient, but might be
> more efficient (by avoiding branches)? And that this code does
> something /useful/ by checking for a sensible maximum pathlength? And
> that any few instruction cycles lost here are negligible compared to the
> hundreds that are needed for copying even a small path string?
As I wrote elsethread, if you are on 32-bit, and cast to 64-bit you
don't really solve the problem, you move it ahead - in other words, you
can't think of handling integer overflow by assuming you always have a
wider type available.
Remember, the topic here is about unsigned wrapping, i.e. integer overflow.
However, without avoiding your point, your alternative works under some
conditions, but it is more wasteful of resources (and as a programmer
involved with microcontrollers and embedded software you are sensible to
this matter), I don't see the benefit of an arbitratry
MAX_SANE_PATHLENGTH - in fact I'd rather not bother about any, and I
don't see how it would be any better than the original.
>
>> And what would be the correct value for MAX_SANE_PATHLENGTH? Are you
>> aware of the trouble that has been caused by Windows MAX_PATH?
>
> You'd pick a big value for it - but a lot less than 4G. Most
> filesystems limit file names to 255 bytes. What would you say is a
> maximum depth of directories before it is clear that you have thoroughly
> screwed up somewhere - maybe 1000? So pick MAX_SANE_PATHLENGTH at 256K
> on 32-bit systems, and 16M on 64-bit systems. People with more
> knowledge of the target system in question can pick better values.
>
> POSIX used to have a limit of 4096, which was okay in the old days but
> got a bit limiting. Windows is limited to 32K now, which seems to be
> fine - the old limit was 260 characters which is clearly too small.
>
>>
>> The example I posted achieves the same level of safety, using less
>> resources, and allowing for the maximum string length that the system
>> can /safely/ handle (don't miss the check after malloc). What more do
>> you want?
>
> See what I wrote above.
>
>>
>>>
>>>
>>> There are times when unsigned wrapping overflow is useful. This is not
>>> one of them.
>>>
>>
>> I suggest you read the code again (and its source - it is instructive)
>
> I did.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-11-07 00:52 +0100 |
| Message-ID | <qpvmcc$n51$1@dont-email.me> |
| In reply to | #69615 |
On 06/11/2019 22:54, Manfred wrote:
> On 11/6/2019 8:36 PM, David Brown wrote:
>> On 06/11/2019 15:38, Manfred wrote:
>>> On 11/6/2019 2:37 PM, David Brown wrote:
>>>> On 06/11/2019 13:33, Manfred wrote:
>>>>> On 11/5/2019 8:45 PM, Paavo Helde wrote:
>>>>>> On 5.11.2019 17:58, Bonita Montero wrote:
>>>>>>>
>>>>>>> With the same reasoning you could say that unsigneds might never
>>>>>>> wrap; but in fact they're specified to wrap.
>>>>>>
>>>>>> In retrospect, this (wrapping unsigneds) looks like a major design
>>>>>> mistake.
>>>>>
>>>>> No, it isn't.
>>>>>
>>>>>>
>>>>>> IMO, wrapping integers (signed or unsigned) are an example of
>>>>>> "optimization which nobody asked for", and they are there basically
>>>>>> only because the hardware happened to support such operations.
>>>>>>
>>>>>
>>>>> Look at the following code and see for yourself how efficient it is to
>>>>> check for integer overflow if unsigned integers do wrap.
>>>>> Achieving the same would be much more verbose (and less efficient) if
>>>>> unsigned overflow were not defined behavior.
>>>>>
>>>>> (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1969.htm)
>>>>>
>>>>> char* make_pathname (const char *dir, const char *fname, const char
>>>>> *ext)
>>>>> {
>>>>> size_t dirlen = strlen (dir);
>>>>> size_t filelen = strlen (fname);
>>>>> size_t extlen = strlen (ext);
>>>>>
>>>>> size_t pathlen = dirlen;
>>>>>
>>>>> // detect and handle integer wrapping
>>>>> if ( (pathlen += filelen) < filelen
>>>>> || (pathlen += extlen) < extlen
>>>>> || (pathlen += 3) < 3)
>>>>> return 0;
>>>>
>>>> That is just silly, in all sorts of ways.
>>>
>>> You realize that this comes from the glibc maintainers, don't you?
>>
>> No. But that doesn't change my opinion - at least not much. It makes
>> a bit more sense if it has to be portable to DOS, for example, with
>> 16-bit size_t.
>>
>>> You can say they wrote silly code for this example (I don't), but I
>>> doubt there are many more knowledgeable people about this kind of
>>> matter than them.
>
> [...]
>
>>>>
>>>> First, decide if the function is an "internal" function where you can
>>>> trust the parameters, and have undefined behaviour if assumptions don't
>>>> hold, or an "external" function where you have to check the validity of
>>>> the parameters.
>>>
>>> This example was written about code safety, so yes, I believe it is
>>> pretty clear the assumption is that strings come from an external
>>> source.
>>> Obviously this applies to string /contents/; the pointer themselves
>>> can only be internal to the program (can't they?), so no need to
>>> check for null pointer.
>>
>> I don't know the circumstances for this function, so I can't answer
>> that. But if it is an externally accessible function, I think checks
>> for null pointers would make sense.
>
> I think there is some misunderstanding about what we mean for "external"
> here, and below.
> This is an example of application code, in the context of code safety,
> that may be written as part of the final program or as part of a
> library. Either way, the pointers are in control of the programmer who
> writes the program, and he does not want to pass null pointers here.
>
That would make it an internal function, not an external function.
Checking for absurd string lengths (and therefore the overflow) is thus
unnecessary.
> Yes, this may happen if there is a mistake somewhere in the program, but
> this is not what code safety is about, it is about code correctness,
> which is a somewhat different thing (although it is true that incorrect
> code is almost certainly unsafe code as well).
> It is for this reason that standard library functions do not check for
> null on all pointers passed in, and I am sure you don't check for null
> within every function you write.
I also don't check sizes, ranges, etc., because my functions are all
internal (since I code for small embedded systems, not libraries).
Functions have a defined set of values that are valid for their
parameters - and they can assume those rules are upheld (baring program
bugs, as you say).
> Code safety as I understand it is about ensuring the program works as
> expected with every kind of data input that is supplied to the /program/
> - like through an I/O stream (kernel safety is a different matter of
> course).
Correct.
> In other words, when you read from std::cin, a file or a socket, you
> allocate a buffer and you know that its pointer is valid. When you reach
> EOF you also know that the buffer is 0-terminated - you place a 0
> yourself if the runtime does not do this for you.
>
> What you don't know (you can't control it) is if the /contents/ between
> the pointer address and the terminating 0 has a valid format, whether it
> is too large or whatever, and that's what you need to ensure that your
> program is robust against in order to be safe.
Agreed. So you check it for validity. 4 GB path strings are not valid
input. You don't need to check for overflow on the sum of the lengths -
you need to check that the data is sane.
>
>>
>>> On the other hand, contents of the string is checked by ensuring that
>>> the result of strlen and their combination is valid. This is ensured
>>> /exactly/ by making use of unsigned wrapping behavior.
>>>
>>
>> The code is going out of its way to check something that is almost
>> impossible to occur, even with malicious intentions - while ignoring
>> problems that could easily occur even by accident.
> See above.
>
>>
>>>>
>>>> If it is internal, you know the lengths of the passed strings will not
>>>> sum to more than 4G - or you don't care if someone does something
>>>> ridiculous. (And on most modern systems, size_t is 64-bit -
>>>> overflowing
>>>> here would require 16 EB ram for storing the strings.)
>>>>
>>>> If it is external, the checking is too little - if you have char*
>>>> pointers from an unknown source, you should be wary about running
>>>> strlen() on them because you don't know if it will actually end with
>>>> a 0
>>>> in a reasonable limit.
>>>
>>> This code handles C strings, so there is no way to check for their
>>> length other than running strlen.
>>
>> size_t limited_strlen(const char* s, size_t n) {
>> const char* p = memchr(s, 0, n);
>> if (!p) return (size_t) -1; // Indicate bad string
>> return p - s;
>> }
>
> Incidentally, this takes a (pointer, length) pair, which is not a C string.
It is checking that the non-null const char * pointer points to a C
string of no greater than n in length. It will return a failure
indication if that is not the case (without bothering to check if it is
a C string that is too long, or if it is not a string at all).
> But that's irrelevant, I explained above that the presence of the
> terminating 0 can and needs to be ensured at the calling level.
The checks need to be made somewhere. I don't know where this function
fits in the scheme of things, so I don't know whether it makes sense to
check in the function, or check before calling the function. But I do
know that calculating the strlen values and checking for overflow on
adding them fails to check for real problems if checks are needed, and
is redundant if checks are not needed.
>
>>
>>> The fact that you seem to miss is that it is exactly thanks to the
>>> check that you call "silly" that it is ensured that they "actually
>>> end with a 0 in a reasonable limit".
>>
>> The checks don't do that. If the three parameters pointed to strings
>> adding up to 4 GB - 1 characters in total, by what stretch of the
>> imagination is that "in a reasonable limit" ?
>
> Define reasonable.
That is the job of the person specifying the function.
> The checks ensure that the code will concat correctly whatever length
> can be /safely/ handled by the system, and handle correctly excessive
> lengths as well, thus covering the entire input domain. That's enough
> for safety, with no need to introduce any dependency on an additional
> and arbitrary parameter.
Nonsense. 4 GB path strings - and 16 EB path strings on 64-bit systems
- cannot be handled safely by the system. They might be blocked by
something further down the chain of calls, but you are not going to
persuade anyone that 4 GB path strings are sensible and can be used
safely for the purpose of dealing with files.
>
>>
>>>
>>> We could argue about what happens with /read/ access to a
>>> non-0-terminated string, but I would simply assume that the strings
>>> are 0 terminated, since the function is going to be called by some
>>> other part of the program that can take care that there is a 0 at the
>>> end of the buffer.
>>
>> Failing to 0 terminate a character sequence that is intended to be a
>> string is not an uncommon bug.
> See above.
>
>>
>>> What is not guaranteed is that the strings actually contain
>>> pathnames, and don't contain very long malicious text instead (e.g.
>>> they could come from stdin).
>>
>> You need text sequences totalling more than 4 GB to cause a problem
>> (and that's on older 32-bit size_t systems). Since the user program
>> can't have as much as 4 GB of data space, you'd need not only huge
>> malicious texts, but you'd also need at least two of the three
>> parameters to overlap.
>>
>>
>>> That risk is avoided by the code you call silly.
>>> So, no there is not too little checking.
>>>
>>>>
>>>>
>>>> You only need to check for overflow if it is possible for the
>>>> calculations to overflow. If the operands are too small to cause an
>>>> overflow, there will not be an overflow.
>>>>
> Yes, keep "if the operands are too small" in mind, and see below.
>
> [...]
>
>>>
>>>>
>>>> So /if/ you have an old 32-bit size_t system, and /if/ you have
>>>> maliciously crafted parameters that point to huge strings (and you'll
>>>> have to make them point within the same string - you don't get over
>>>> 4 GB
>>>> user memory address space with 32-bit size_t), then you can do your
>>>> adding up using 64-bit types and you get zero risk of overflow.
>>>>
>>>>
>>>> uint_least64_t dirlen = strlen (dir);
>>>> uint_least64_t filelen = strlen (fname);
>>>> uint_least64_t extlen = strlen (ext);
>>>>
>>>> uint_least64_t pathlen = dirlen + filelen + extlen;
>>>>
>>>> if (big_size_t > MAX_SANE_PATHLENGTH) return 0;
>>>
>>> You realize that this code is less efficient than the original one,
>>> don't you?
>>
>> You realise that it is /more/ efficient on any 64-bit system?
>
> Watch out: you wrote this example for 32-bit, but on 64 bit it can fail
> for large enough inputs:
>
> // the following /can/ now silently overflow
> >>> uint_least64_t pathlen = dirlen + filelen + extlen;
> >>>
> >>> if (big_size_t > MAX_SANE_PATHLENGTH) return 0;
>
> That is, on 64-bit it becomes unsafe.
I know exactly what I wrote. And I know that it is safe - because you
won't get overflow until strlen has finished counting these 16 PB long
strings, and the earth has melted into the dying sun.
>
> And that
>> on 32-bit systems it is at most marginally less efficient, but might
>> be more efficient (by avoiding branches)? And that this code does
>> something /useful/ by checking for a sensible maximum pathlength? And
>> that any few instruction cycles lost here are negligible compared to
>> the hundreds that are needed for copying even a small path string?
> As I wrote elsethread, if you are on 32-bit, and cast to 64-bit you
> don't really solve the problem, you move it ahead - in other words, you
> can't think of handling integer overflow by assuming you always have a
> wider type available.
> Remember, the topic here is about unsigned wrapping, i.e. integer overflow.
And I have been demonstrating how it is not appropriate in your example
- it is neither necessary nor sufficient.
>
> However, without avoiding your point, your alternative works under some
> conditions, but it is more wasteful of resources (and as a programmer
> involved with microcontrollers and embedded software you are sensible to
> this matter), I don't see the benefit of an arbitratry
> MAX_SANE_PATHLENGTH - in fact I'd rather not bother about any, and I
> don't see how it would be any better than the original.
>
Sorry, but my solution is /not/ wasteful of resources on a realistic
system - it is more efficient for 64-bit systems.
(You would be unlikely to have such a function on a small
microcontroller, and you know your limits on such a system - you would
not need to check for overflow.)
>>
>>> And what would be the correct value for MAX_SANE_PATHLENGTH? Are you
>>> aware of the trouble that has been caused by Windows MAX_PATH?
>>
>> You'd pick a big value for it - but a lot less than 4G. Most
>> filesystems limit file names to 255 bytes. What would you say is a
>> maximum depth of directories before it is clear that you have
>> thoroughly screwed up somewhere - maybe 1000? So pick
>> MAX_SANE_PATHLENGTH at 256K on 32-bit systems, and 16M on 64-bit
>> systems. People with more knowledge of the target system in question
>> can pick better values.
>>
>> POSIX used to have a limit of 4096, which was okay in the old days but
>> got a bit limiting. Windows is limited to 32K now, which seems to be
>> fine - the old limit was 260 characters which is clearly too small.
>>
>>>
>>> The example I posted achieves the same level of safety, using less
>>> resources, and allowing for the maximum string length that the system
>>> can /safely/ handle (don't miss the check after malloc). What more do
>>> you want?
>>
>> See what I wrote above.
>>
>>>
>>>>
>>>>
>>>> There are times when unsigned wrapping overflow is useful. This is not
>>>> one of them.
>>>>
>>>
>>> I suggest you read the code again (and its source - it is instructive)
>>
>> I did.
>
Then let's leave it there. I don't think there is much to be gained by
continuing in this line.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-11-06 17:54 +0200 |
| Message-ID | <qpuqci$f5e$1@dont-email.me> |
| In reply to | #69589 |
On 6.11.2019 14:33, Manfred wrote:
> On 11/5/2019 8:45 PM, Paavo Helde wrote:
>> On 5.11.2019 17:58, Bonita Montero wrote:
>>>
>>> With the same reasoning you could say that unsigneds might never
>>> wrap; but in fact they're specified to wrap.
>>
>> In retrospect, this (wrapping unsigneds) looks like a major design
>> mistake.
>
> No, it isn't.
>
>>
>> IMO, wrapping integers (signed or unsigned) are an example of
>> "optimization which nobody asked for", and they are there basically
>> only because the hardware happened to support such operations.
>>
>
> Look at the following code and see for yourself how efficient it is to
> check for integer overflow if unsigned integers do wrap.
> Achieving the same would be much more verbose (and less efficient) if
> unsigned overflow were not defined behavior.
>
> (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1969.htm)
>
> char* make_pathname (const char *dir, const char *fname, const char *ext)
> {
> size_t dirlen = strlen (dir);
> size_t filelen = strlen (fname);
> size_t extlen = strlen (ext);
>
> size_t pathlen = dirlen;
>
> // detect and handle integer wrapping
> if ( (pathlen += filelen) < filelen
> || (pathlen += extlen) < extlen
> || (pathlen += 3) < 3)
> return 0;
>
> char *p, *path = malloc (pathlen);
> if (!path)
> return 0;
>
> p = memcpy (path, dir, dirlen);
> p [dirlen] = '/';
>
> p = memcpy (p + dirlen + 1, fname, filelen);
> p [filelen] = '.';
>
> memcpy (p + filelen + 1, ext, extlen + 1);
>
> return path;
> }
Seriously?
std::string make_pathname(const std::string& dir,
const std::string& fname, const std::string& ext)
{
return dir + "/" + fname + "." + ext;
}
No need to check for any overflows.
Not to speak about that there cannot be overflow in the first place
because if pathlen overflows the three strings dir, fname and ext would
not fit in the process memory anyway.
Not to speak about that the time lost for a more explicit check for
overflow would be zero or unmeasurable, compared to any file access
itself, or even when compared to the malloc() call in the same function.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2019-11-06 18:15 +0100 |
| Message-ID | <qpuv49$1mgn$1@gioia.aioe.org> |
| In reply to | #69597 |
On 11/6/2019 4:54 PM, Paavo Helde wrote:
> On 6.11.2019 14:33, Manfred wrote:
>> On 11/5/2019 8:45 PM, Paavo Helde wrote:
>>> On 5.11.2019 17:58, Bonita Montero wrote:
>>>>
>>>> With the same reasoning you could say that unsigneds might never
>>>> wrap; but in fact they're specified to wrap.
>>>
>>> In retrospect, this (wrapping unsigneds) looks like a major design
>>> mistake.
>>
>> No, it isn't.
>>
>>>
>>> IMO, wrapping integers (signed or unsigned) are an example of
>>> "optimization which nobody asked for", and they are there basically
>>> only because the hardware happened to support such operations.
>>>
>>
>> Look at the following code and see for yourself how efficient it is to
>> check for integer overflow if unsigned integers do wrap.
>> Achieving the same would be much more verbose (and less efficient) if
>> unsigned overflow were not defined behavior.
>>
>> (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1969.htm)
>>
>> char* make_pathname (const char *dir, const char *fname, const char *ext)
>> {
>> size_t dirlen = strlen (dir);
>> size_t filelen = strlen (fname);
>> size_t extlen = strlen (ext);
>>
>> size_t pathlen = dirlen;
>>
>> // detect and handle integer wrapping
>> if ( (pathlen += filelen) < filelen
>> || (pathlen += extlen) < extlen
>> || (pathlen += 3) < 3)
>> return 0;
>>
>> char *p, *path = malloc (pathlen);
>> if (!path)
>> return 0;
>>
>> p = memcpy (path, dir, dirlen);
>> p [dirlen] = '/';
>>
>> p = memcpy (p + dirlen + 1, fname, filelen);
>> p [filelen] = '.';
>>
>> memcpy (p + filelen + 1, ext, extlen + 1);
>>
>> return path;
>> }
>
> Seriously?
>
> std::string make_pathname(const std::string& dir,
> const std::string& fname, const std::string& ext)
> {
> return dir + "/" + fname + "." + ext;
> }
>
> No need to check for any overflows.
How do you think that overflow check is done inside std::string?
>
> Not to speak about that there cannot be overflow in the first place
> because if pathlen overflows the three strings dir, fname and ext would
> not fit in the process memory anyway.
>
> Not to speak about that the time lost for a more explicit check for
> overflow would be zero or unmeasurable, compared to any file access
> itself, or even when compared to the malloc() call in the same function.
>
>
What do you mean with "more explicit check for overflow"?
Assuming you know the variables are 32-bit unsigned, I suppose you could do
if (pathlen < 0xFFFFFFFF-filelen)
{
pathlen += filelen;
}
else
{
return 0;
}
and then repeat, but honestly I don't see the benefit of it compared to
the above (as a first you are introducing a dependency on the specific
integer size).
Or you can cast to a wider type, but then you are not solving the
problem, you are only moving it forward, and still I wouldn't see the
benefit.
Besides, this is about /integer/ overflow check, so it could apply to
more computations other than memory size.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2019-11-06 18:33 +0100 |
| Message-ID | <qpv05f$nvc$1@news.albasani.net> |
| In reply to | #69601 |
> What do you mean with "more explicit check for overflow"? concatenating strings in C++ with the + opereator is reliable.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2019-11-06 10:55 -0800 |
| Message-ID | <cf4a4cc6-a3a3-4697-b870-313c067be68e@googlegroups.com> |
| In reply to | #69601 |
On Wednesday, 6 November 2019 19:16:08 UTC+2, Manfred wrote:
> On 11/6/2019 4:54 PM, Paavo Helde wrote:
> > Seriously?
> >
> > std::string make_pathname(const std::string& dir,
> > const std::string& fname, const std::string& ext)
> > {
> > return dir + "/" + fname + "." + ext;
> > }
> >
> > No need to check for any overflows.
>
> How do you think that overflow check is done inside std::string?
All standard library writers are rather good programmers.
Obviously they have something that is easy to read from afar that it does
no way overflow. Likely it is some short inline member to call
when size is supposed to grow that does the check:
if (max_size() - size() < size_to_add)
throw std::length_error(text_to_throw);
Why don't you look into any of implementations in your computer?
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2019-11-06 20:15 +0100 |
| Message-ID | <qpv657$8rg$2@news.albasani.net> |
| In reply to | #69603 |
> All standard library writers are rather good programmers. Another aspect is: if millions of developers reuse code instead of writing it on their own, errors will be noticed for sure; but when you do everything yourself, a lot of errors won't be noticed.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2019-11-06 20:53 +0100 |
| Message-ID | <qpv8ca$12a1$1@gioia.aioe.org> |
| In reply to | #69603 |
On 11/6/2019 7:55 PM, Öö Tiib wrote:
> On Wednesday, 6 November 2019 19:16:08 UTC+2, Manfred wrote:
>> On 11/6/2019 4:54 PM, Paavo Helde wrote:
>>> Seriously?
>>>
>>> std::string make_pathname(const std::string& dir,
>>> const std::string& fname, const std::string& ext)
>>> {
>>> return dir + "/" + fname + "." + ext;
>>> }
>>>
>>> No need to check for any overflows.
>>
>> How do you think that overflow check is done inside std::string?
>
> All standard library writers are rather good programmers.
> Obviously they have something that is easy to read from afar that it does
> no way overflow. Likely it is some short inline member to call
> when size is supposed to grow that does the check:
>
> if (max_size() - size() < size_to_add)
> throw std::length_error(text_to_throw);
>
> Why don't you look into any of implementations in your computer?
>
My reply was about the comment "No need to check for any overflows." -
obviously if you do C++ programming you need to know how to check for
integer overflow (and we all know how to use '+' with std::string, but
we may also need to calculate e.g. a length of a std::vector to resize,
and check for overflow in the process)
The fragment you posted obviously works well with no need for unsigned
wrapping (I didn't say you can't do without, I said it's more efficient
and less verbose if you have it), but it also has different requirements
than the example I posted: two strings only, with the precondition that
the 'this' string is less than max_size() long.
Just to stick with this example (although my point was about integer
overflow rather than string concatenation), you see that if you lift
these preconditions and need to concat more than 2 strings (as it was in
the example) then either you precalculate the total length of the final
string with a series of additions (and you see that the example is more
efficient, more clear and less verbose than a series of if/else) or you
do string+string+string and you end up with multiple allocations and
copies (and yes, as often as this is totally irrelevant, sometimes this
does matter).
This is to say that if you want to handle integer overflow efficiently,
then unsigned wrapping /is/ useful, it is not a "major design mistake" -
which is what triggered all this (for me at least).
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-11-06 22:25 +0200 |
| Message-ID | <qpva7j$hlr$1@dont-email.me> |
| In reply to | #69609 |
On 6.11.2019 21:53, Manfred wrote:
> Just to stick with this example (although my point was about integer
> overflow rather than string concatenation), you see that if you lift
> these preconditions and need to concat more than 2 strings (as it was in
> the example) then either you precalculate the total length of the final
> string with a series of additions (and you see that the example is more
> efficient, more clear and less verbose than a series of if/else) or you
> do string+string+string and you end up with multiple allocations and
> copies (and yes, as often as this is totally irrelevant, sometimes this
> does matter).
If the profiler shows the multiple allocations in this function are
creating a bottleneck, you can avoid this easily:
std::string make_pathname(const std::string& dir,
const std::string& fname, const std::string& ext)
{
std::string result;
result.reserve(dir.length()+fname.length()+ext.length()+2);
result += dir;
result += '/';
result += fname;
result += '.';
result += ext;
return result;
}
There is still no need to check for overflow.
Note that if there is an overflow, reserve() will reserve less memory
than needed, but that's OK because the later += operations will check
for it anyway.
And if a future C++ implementation makes unsigned wrapping undefined and
the above addition overflows, triggers an assertion and terminates the
program, then this would be a better result than trying to compose a
filename which won't fit in memory.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2019-11-06 23:05 +0100 |
| Message-ID | <qpvg35$6tc$1@gioia.aioe.org> |
| In reply to | #69612 |
On 11/6/2019 9:25 PM, Paavo Helde wrote:
> On 6.11.2019 21:53, Manfred wrote:
>> Just to stick with this example (although my point was about integer
>> overflow rather than string concatenation), you see that if you lift
>> these preconditions and need to concat more than 2 strings (as it was in
>> the example) then either you precalculate the total length of the final
>> string with a series of additions (and you see that the example is more
>> efficient, more clear and less verbose than a series of if/else) or you
>> do string+string+string and you end up with multiple allocations and
>> copies (and yes, as often as this is totally irrelevant, sometimes this
>> does matter).
>
> If the profiler shows the multiple allocations in this function are
> creating a bottleneck, you can avoid this easily:
>
> std::string make_pathname(const std::string& dir,
> const std::string& fname, const std::string& ext)
> {
> std::string result;
> result.reserve(dir.length()+fname.length()+ext.length()+2);
> result += dir;
> result += '/';
> result += fname;
> result += '.';
> result += ext;
> return result;
> }
>
> There is still no need to check for overflow.
>
> Note that if there is an overflow, reserve() will reserve less memory
> than needed, but that's OK because the later += operations will check
> for it anyway.
Note that here you are still assuming wrapping.
>
> And if a future C++ implementation makes unsigned wrapping undefined
Undefined? Then I believe it wouldn't work.
and
> the above addition overflows, triggers an assertion and terminates the
> program, then this would be a better result than trying to compose a
> filename which won't fit in memory.
>
And here you are still assuming defined behavior (implying that every
single integer operation is checked at runtime).
Moreover, program termination is /not/ safe coding - you know what DoS
attack is.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-11-07 10:23 +0200 |
| Message-ID | <qq0k9d$pq1$1@dont-email.me> |
| In reply to | #69616 |
On 7.11.2019 0:05, Manfred wrote:
> On 11/6/2019 9:25 PM, Paavo Helde wrote:
and
>> the above addition overflows, triggers an assertion and terminates the
>> program, then this would be a better result than trying to compose a
>> filename which won't fit in memory.
>>
> And here you are still assuming defined behavior (implying that every
> single integer operation is checked at runtime).
> Moreover, program termination is /not/ safe coding - you know what DoS
> attack is.
Yes, one needs to protect against attacks. However, if somebody has
managed to send in gigabytes or exabytes of path strings into my program
the DoS attack has already happened, as storing and processing them will
take a lot of resources.
I agree that one needs to check against overflows where appropriate, but
this pathname concatenation example is about the silliest one could
imagine. If you look at the original page
"http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1969.htm" you see that
this is not the part he is demonstrating or discussing (it's not colored
in red like rsize_t additions). That's just some lines which he has
copied over from the earlier "unsafe" sample without any changes. He
does not argue that this is the best way to check for integer overflows,
that's just some copy-paste lines which are short and do no harm.
Note that the whole page is about *buffer overflows*, not *integer
overflows*.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-11-06 22:20 +0100 |
| Message-ID | <qpvde4$5c9$1@dont-email.me> |
| In reply to | #69609 |
On 06/11/2019 20:53, Manfred wrote:
> This is to say that if you want to handle integer overflow efficiently,
> then unsigned wrapping /is/ useful, it is not a "major design mistake" -
> which is what triggered all this (for me at least).
I partly agree on this (despite disagreeing about the example you gave).
Unsigned wrapping is one way to handle integer overflow efficiently.
It is not the only way, and not necessarily the best way, but it can
sometimes be useful.
One thing to note is that when the checks are handled within the
standard library (such as for C++ string concatenation), the
implementation does not need to stick to portable, standard C++. A gcc
standard library could use "#pragma GCC optimize(("fwrapv"))" and
wrapping signed integer arithmetic, if it preferred. Or it could use
__int128 types, or the overflow __builtins - whatever gives the best
results.
But if you are writing portable, standard C or C++ and need to check for
overflows, unsigned wrapping is sometimes the best solution.
However, I would say that the main reason for having unsigned integers
wrap is simply that sometimes you want wrapping behaviour - overflow
detection is only one of a number of possible applications for wrapping.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-11-06 22:12 +0200 |
| Message-ID | <qpv9f2$cno$1@dont-email.me> |
| In reply to | #69601 |
On 6.11.2019 19:15, Manfred wrote:
> On 11/6/2019 4:54 PM, Paavo Helde wrote:
>
>> std::string make_pathname(const std::string& dir,
>> const std::string& fname, const std::string& ext)
>> {
>> return dir + "/" + fname + "." + ext;
>> }
>>
>> No need to check for any overflows.
>
> How do you think that overflow check is done inside std::string?
I'm pretty confident it's done properly. Note that std::string would
even be allowed to use implementation-specific features which are UB by
the standard, should it be necessary.
>>
>> Not to speak about that there cannot be overflow in the first place
>> because if pathlen overflows the three strings dir, fname and ext
>> would not fit in the process memory anyway.
>>
>> Not to speak about that the time lost for a more explicit check for
>> overflow would be zero or unmeasurable, compared to any file access
>> itself, or even when compared to the malloc() call in the same function.
>>
>>
>
> What do you mean with "more explicit check for overflow"?
>
> Assuming you know the variables are 32-bit unsigned, I suppose you could do
> if (pathlen < 0xFFFFFFFF-filelen)
> {
> pathlen += filelen;
> }
> else
> {
> return 0;
> }
Yes, that's what I meant by "more explicit". And there is
std::numeric_limits<T>::max(), no need for 0xFFFFFFFFF magic numbers.
>
> and then repeat, but honestly I don't see the benefit of it compared to
> the above (as a first you are introducing a dependency on the specific
> integer size).
> Or you can cast to a wider type, but then you are not solving the
> problem, you are only moving it forward, and still I wouldn't see the
> benefit.
To be honest, the check I would wrote would be something along to:
if (strlen(filename)>10000) {
throw std::runtime_error("You must be kidding");
}
and it would happen way before any make_pathname() function.
>
> Besides, this is about /integer/ overflow check, so it could apply to
> more computations other than memory size.
No, the variables in your example were size_t.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-11-09 06:24 -0800 |
| Message-ID | <86lfspcekw.fsf@linuxsc.com> |
| In reply to | #69575 |
Paavo Helde <myfirstname@osa.pri.ee> writes: > On 5.11.2019 17:58, Bonita Montero wrote: > >> With the same reasoning you could say that unsigneds might never >> wrap; but in fact they're specified to wrap. > > In retrospect, this (wrapping unsigneds) looks like a major design mistake. > > IMO, wrapping integers (signed or unsigned) are an example of > "optimization which nobody asked for", and they are there basically > only because the hardware happened to support such operations. Apparently you think how the hardware behaves (specifically, for unsigned or two's complement operands) is some sort of accident of history. It isn't. It was a deliberate choice, made by smart people. It isn't just a coincidence that the semantics of wrapping works nicely in a variety of applications.
[toc] | [prev] | [next] | [standalone]
| From | Siri Cruise <chine.bleu@yahoo.com> |
|---|---|
| Date | 2019-11-09 07:14 -0700 |
| Message-ID | <chine.bleu-C27EF7.07143109112019@reader.eternal-september.org> |
| In reply to | #69679 |
In article <86lfspcekw.fsf@linuxsc.com>, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote: > Paavo Helde <myfirstname@osa.pri.ee> writes: > > > On 5.11.2019 17:58, Bonita Montero wrote: > > > >> With the same reasoning you could say that unsigneds might never > >> wrap; but in fact they're specified to wrap. > > > > In retrospect, this (wrapping unsigneds) looks like a major design mistake. > > > > IMO, wrapping integers (signed or unsigned) are an example of > > "optimization which nobody asked for", and they are there basically > > only because the hardware happened to support such operations. > > Apparently you think how the hardware behaves (specifically, for > unsigned or two's complement operands) is some sort of accident > of history. It isn't. It was a deliberate choice, made by smart > people. It isn't just a coincidence that the semantics of > wrapping works nicely in a variety of applications. CPUs with an overflow flag note additions that overflow the register. A compiler can implement integer overflow exceptions on such CPUs. -- :-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @ 'I desire mercy, not sacrifice.' /|\ The first law of discordiamism: The more energy This post / \ to make order is nore energy made into entropy. insults Islam. Mohammed
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-11-10 11:52 +0100 |
| Message-ID | <qq8q4n$n4c$1@dont-email.me> |
| In reply to | #69679 |
On 09/11/2019 15:24, Tim Rentsch wrote: > Paavo Helde <myfirstname@osa.pri.ee> writes: > >> On 5.11.2019 17:58, Bonita Montero wrote: >> >>> With the same reasoning you could say that unsigneds might never >>> wrap; but in fact they're specified to wrap. >> >> In retrospect, this (wrapping unsigneds) looks like a major design mistake. >> >> IMO, wrapping integers (signed or unsigned) are an example of >> "optimization which nobody asked for", and they are there basically >> only because the hardware happened to support such operations. > > Apparently you think how the hardware behaves (specifically, for > unsigned or two's complement operands) is some sort of accident > of history. It isn't. It was a deliberate choice, made by smart > people. It isn't just a coincidence that the semantics of > wrapping works nicely in a variety of applications. > Wrapping in hardware was not a deliberate choice of semantics - it was a deliberate choice of the simplest, fastest and most efficient hardware with little concern for the semantics. There are three primary choices for defined behaviour of signed integer overflow - saturation, trapping, and wrapping. None of these matches mathematical integer behaviour, of course. Saturation is a natural and useful choice in many circumstances. Trapping (including NaN implementations) is a good way of seeing that something has gone wrong, so that you either have the right answer, or know there has been an error. Wrapping has no logical use or point as a semantic of an operation. It is, however, a very convenient aid to multi-precision arithmetic. Implementations of signed integer representations other than two's complement, such as ones' complement and sign-magnitude, do not typically have wrapping semantics - they will have trapping or saturation semantics, if they have defined semantics. But in hardware, two's complement representation is the simplest and most efficient method. And if you have wrapping for addition and subtraction, it becomes easily expandable - a vital feature from the days of 8-bit ALU's being used for 16-bit, 32-bit and larger arithmetic, and still useful occasionally. This is related to the reason why in many cpu's, there is a "carry" flag for addition that doubles as the "not borrow" flag for subtraction - it means you implement your subtraction "x - y" as "x + ~y" and re-use almost all the hardware elements. Saturation and trapping cost hardware - the wrapping is free. It would be the standard in hardware even if it didn't have the use for multi-precision arithmetic. Paavo is right when viewed from the high-level software perspective - wrapping is not something people looked for, either for signed or unsigned arithmetic. For very low-level software, it /is/ useful in the case where you are building up larger arithmetic operations from smaller ones, and for certain kinds of comparisons - these are things that are mostly hidden by the compiler in a high level language like C.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-11-10 16:31 +0200 |
| Message-ID | <qq96vl$7iq$1@dont-email.me> |
| In reply to | #69679 |
On 9.11.2019 16:24, Tim Rentsch wrote: > Paavo Helde <myfirstname@osa.pri.ee> writes: > >> On 5.11.2019 17:58, Bonita Montero wrote: >> >>> With the same reasoning you could say that unsigneds might never >>> wrap; but in fact they're specified to wrap. >> >> In retrospect, this (wrapping unsigneds) looks like a major design mistake. >> >> IMO, wrapping integers (signed or unsigned) are an example of >> "optimization which nobody asked for", and they are there basically >> only because the hardware happened to support such operations. > > Apparently you think how the hardware behaves (specifically, for > unsigned or two's complement operands) is some sort of accident > of history. It isn't. It was a deliberate choice, made by smart > people. It isn't just a coincidence that the semantics of > wrapping works nicely in a variety of applications. The hardware which I am familiar with properly sets the carry and overflow flags for arithmetic operations. In case of multiplication it also produces the result twice larger than the operands, in order to not lose information. So at the hardware level the results are always well-defined and complete, this is very fine. The calling program can study the flags and decide what to do about this. The problem with C is that they decided the best way to deal with this is just to ignore the overflow flag and the upper half of the multiplication result. Not sure about PDP-11 itself, but they had to think about other hardware too, and at some point they decided that the best way to deal with the problem was just to ignore all the extra information the current or future CPU-s might provide. An imaginary conversation: A: BTW, what should we do with the arithmetic overflow? There are overflow flags and extended precision results in some hardware that we could use. B: Because of speed and simplicity, we just ignore it. Each extra opcode would slow us down! A: But in case of multiplication, we might lose half of the result! B. Just ignore it. A. But what we write down in the specs? We can't just say we carry out an hardware operation and then ignore everything except the first result register. B. Let's see... Isn't there a nice name for that behavior? Yep, it's called wrapping! Write this down in the specs! A. But, but, with signed integers, there are different representations, so that on some hardware it does not actually wrap! B. Ouch, my head is hurting. Just declare it undefined then!
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2019-11-10 19:02 +0100 |
| Message-ID | <qq9jbb$gap$1@gioia.aioe.org> |
| In reply to | #69701 |
On 11/10/19 3:31 PM, Paavo Helde wrote: > On 9.11.2019 16:24, Tim Rentsch wrote: >> Paavo Helde <myfirstname@osa.pri.ee> writes: >> >>> On 5.11.2019 17:58, Bonita Montero wrote: >>> >>>> With the same reasoning you could say that unsigneds might never >>>> wrap; but in fact they're specified to wrap. >>> >>> In retrospect, this (wrapping unsigneds) looks like a major design >>> mistake. >>> >>> IMO, wrapping integers (signed or unsigned) are an example of >>> "optimization which nobody asked for", and they are there basically >>> only because the hardware happened to support such operations. >> >> Apparently you think how the hardware behaves (specifically, for >> unsigned or two's complement operands) is some sort of accident >> of history. It isn't. It was a deliberate choice, made by smart >> people. It isn't just a coincidence that the semantics of >> wrapping works nicely in a variety of applications. > > The hardware which I am familiar with properly sets the carry and > overflow flags for arithmetic operations. In case of multiplication it > also produces the result twice larger than the operands, in order to not > lose information. So at the hardware level the results are always > well-defined and complete, this is very fine. The calling program can > study the flags and decide what to do about this. The main difference between the hardware and the language is that 1) the former can count on accessory entities that are not part of a variable (the flags register) and 2) it does not have to fit within the semantics of a type system, so that it is OK for WORD op WORD to yield DWORD If you go into the specifics, you may see that: 1) flags information would need to be handled by the compiler, with the possible result of littering the generated code with branches for every integer expression. 2) Having an arithmetic operator (multiplication) yield a different type than the operands would pose significant complications to the language - if you really want this, try mimicking that with some C++ wrapper classes and operators thereof, and see where you go. The solution, when the full range is needed, is to tell the compiler that this is what you want by casting the /operands/. In this way the compiler can deliver the result you want (while optimizing away the extra space for the operands themselves). > > The problem with C is that they decided the best way to deal with this > is just to ignore the overflow flag and the upper half of the > multiplication result. Not sure about PDP-11 itself, but they had to > think about other hardware too, and at some point they decided that the > best way to deal with the problem was just to ignore all the extra > information the current or future CPU-s might provide See above. Moreover, given the impact of the choice, and its business consequences, it is hard to believe that this was just sloppiness. > > An imaginary conversation: > > A: BTW, what should we do with the arithmetic overflow? There are > overflow flags and extended precision results in some hardware that we > could use. > > B: Because of speed and simplicity, we just ignore it. Each extra opcode > would slow us down! > > A: But in case of multiplication, we might lose half of the result! > > B. Just ignore it. > > A. But what we write down in the specs? We can't just say we carry out > an hardware operation and then ignore everything except the first result > register. > > B. Let's see... Isn't there a nice name for that behavior? Yep, it's > called wrapping! Write this down in the specs! > > A. But, but, with signed integers, there are different representations, > so that on some hardware it does not actually wrap! > > B. Ouch, my head is hurting. Just declare it undefined then! > > This is fiction.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-11-11 12:08 +0200 |
| Message-ID | <qqbbvo$fce$1@dont-email.me> |
| In reply to | #69706 |
On 10.11.2019 20:02, Manfred wrote: > The main difference between the hardware and the language is that 1) the > former can count on accessory entities that are not part of a variable > (the flags register) and 2) it does not have to fit within the semantics > of a type system, so that it is OK for WORD op WORD to yield DWORD > > If you go into the specifics, you may see that: > 1) flags information would need to be handled by the compiler, with the > possible result of littering the generated code with branches for every > integer expression. Yes, that's correct. > 2) Having an arithmetic operator (multiplication) yield a different type > than the operands would pose significant complications to the language - > if you really want this, try mimicking that with some C++ wrapper > classes and operators thereof, and see where you go. > The solution, when the full range is needed, is to tell the compiler > that this is what you want by casting the /operands/. > In this way the compiler can deliver the result you want (while > optimizing away the extra space for the operands themselves). Note that when the operands are cast to suitable larger types, then overflow cannot happen, so for this usage case the overflow behavior does not need to be defined. > >> >> The problem with C is that they decided the best way to deal with this >> is just to ignore the overflow flag and the upper half of the >> multiplication result. Not sure about PDP-11 itself, but they had to >> think about other hardware too, and at some point they decided that >> the best way to deal with the problem was just to ignore all the extra >> information the current or future CPU-s might provide > > See above. > Moreover, given the impact of the choice, and its business consequences, > it is hard to believe that this was just sloppiness. Of course not. The decision to produce fastest code was a deliberate choice made by smart people, as you said. Any kind of overflow checking would have slowed the code down at least twice, which would have been of course disastrous for a language meant as "better assembler". With the specified wrapping behavior for unsigneds the story is different however. They defined the unsigned overflow as wrapping because they could, not because of some deeper considerations. Would the existing hardware have provided some other behavior (like saturating) at zero cost, I'm sure they would have standardized that behavior instead. Note that they did not just copy the hardware behavior. The common hardware itself does not have wrapping behavior, rather it produces the correct result with carry/overflow flags and extended registers. One only gets wrapping behavior by deliberately ignoring the correct result. In a similar token, they did not define the behavior for signed overflow because they couldn't. More specifically, the zero cost behavior was different on different hardware, and they could not find enough justification for any kind of non-zero cost overflow behavior.
[toc] | [prev] | [next] | [standalone]
Page 2 of 11 — ← Prev page 1 [2] 3 4 … 11 Next page →
Back to top | Article view | comp.lang.c++
csiph-web