zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.stephenson@samsung.com>
To: zsh-workers@zsh.org
Subject: Re: [BUG] printf truncates large values
Date: Tue, 30 Jan 2018 18:30:42 +0000	[thread overview]
Message-ID: <20180130183042.7e013804@pwslap01u.europe.root.pri> (raw)
In-Reply-To: <20180130164021.GA521@cventin.lip.ens-lyon.fr>

On Tue, 30 Jan 2018 17:40:21 +0100
Vincent Lefevre <vincent@vinc17.net> wrote:
> On a 64-bit x86_64 machine, with zsh 5.4.2:
> 
> cventin% printf "%x\n" 10865468317030705979
> zsh: number truncated after 19 digits: 10865468317030705979
> f1430962f7cd785

This is not because of the standard integer representation, it relates
to whatever type we picked for zlong (and the corresponding unsigned
type, zulong, which has the same length).

The problem is this goes through math evaluation (mathevali())
regardless of the fact that it's a constant, so becomes a zlong.  This
means we lose track of the fact it's actually unsigned.

The only easyish fix is to scan for a constant and avoid the mathevali()
in that case.  So I copied and adapted zstrtol_underscore() to do that.
Anything more requires propagating full-length unsigned values
separately through the integer code, which is a large undertaking not
entirely without its own problems.

pws

diff --git a/Src/builtin.c b/Src/builtin.c
index 0211f27..fb59738 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -5243,7 +5243,10 @@ bin_print(char *name, char **args, Options ops, int func)
  		    	*d++ = 'l';
 #endif
 		    	*d++ = 'l', *d++ = *c, *d = '\0';
-			zulongval = (curarg) ? mathevali(curarg) : 0;
+			if (!curarg)
+			    zulongval = (zulong)0;
+			else if (!zstrtoul_underscore(curarg, &zulongval))
+			    zulongval = mathevali(curarg);
 			if (errflag) {
 			    zulongval = 0;
 			    errflag &= ~ERRFLAG_ERROR;
diff --git a/Src/utils.c b/Src/utils.c
index 74fdac3..3b589aa 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2455,6 +2455,67 @@ zstrtol_underscore(const char *s, char **t, int base, int underscore)
     return neg ? -(zlong)calc : (zlong)calc;
 }
 
+/*
+ * If s represents a complete unsigned integer (and nothing else)
+ * return 1 and set retval to the value.  Otherwise return 0.
+ *
+ * Underscores are always allowed.
+ *
+ * Sensitive to OCTAL_ZEROES.
+ */
+
+/**/
+mod_export int
+zstrtoul_underscore(const char *s, zulong *retval)
+{
+    zulong calc = 0, newcalc = 0, base;
+
+    if (*s == '+')
+	s++;
+
+    if (*s != '0')
+	base = 10;
+    else if (*++s == 'x' || *s == 'X')
+	base = 16, s++;
+    else if (*s == 'b' || *s == 'B')
+	base = 2, s++;
+    else
+	base = isset(OCTALZEROES) ? 8 : 10;
+    if (base < 2 || base > 36) {
+	return 0;
+    } else if (base <= 10) {
+	for (; (*s >= '0' && *s < ('0' + base)) ||
+		 *s == '_'; s++) {
+	    if (*s == '_')
+		continue;
+	    newcalc = calc * base + *s - '0';
+	    if (newcalc < calc)
+	    {
+		return 0;
+	    }
+	    calc = newcalc;
+	}
+    } else {
+	for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10))
+	     || (*s >= 'A' && *s < ('A' + base - 10))
+	     || *s == '_'; s++) {
+	    if (*s == '_')
+		continue;
+	    newcalc = calc*base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9);
+	    if (newcalc < calc)
+	    {
+		return 0;
+	    }
+	    calc = newcalc;
+	}
+    }
+
+    if (*s)
+	return 0;
+    *retval = calc;
+    return 1;
+}
+
 /**/
 mod_export int
 setblock_fd(int turnonblocking, int fd, long *modep)


      reply	other threads:[~2018-01-30 18:41 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20180130164832epcas1p1460baafa538692bcc1f9b169f00f0bc5@epcas1p1.samsung.com>
2018-01-30 16:40 ` Vincent Lefevre
2018-01-30 18:30   ` Peter Stephenson [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180130183042.7e013804@pwslap01u.europe.root.pri \
    --to=p.stephenson@samsung.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).