Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jan 2020 20:25:11 +0000 (UTC)
From:      Garance A Drosehn <gad@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356666 - in head/usr.bin: factor primes
Message-ID:  <202001122025.00CKPBSW071370@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gad
Date: Sun Jan 12 20:25:11 2020
New Revision: 356666
URL: https://svnweb.freebsd.org/changeset/base/356666

Log:
  Fix the way 'factor' behaves when using OpenSSL to match the description
  of how it works when not compiled with OpenSSL.
  
  Also, allow users to specify a hexadecimal number by using a prefix of
  '0x'.  Before this, users could only specify a hexadecimal value if that
  value included a hex digit ('a'-'f') in the value.
  
  PR:		243136
  Submitted by:	Steve Kargl
  Reviewed by:	gad
  MFC after:	3 weeks

Modified:
  head/usr.bin/factor/factor.6
  head/usr.bin/factor/factor.c
  head/usr.bin/primes/primes.c

Modified: head/usr.bin/factor/factor.6
==============================================================================
--- head/usr.bin/factor/factor.6	Sun Jan 12 20:19:00 2020	(r356665)
+++ head/usr.bin/factor/factor.6	Sun Jan 12 20:25:11 2020	(r356666)
@@ -36,7 +36,7 @@
 .\"
 .\"   chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
 .\"
-.Dd October 10, 2002
+.Dd January 12, 2020
 .Dt FACTOR 6
 .Os
 .Sh NAME
@@ -67,11 +67,22 @@ When
 .Nm
 is invoked with no arguments,
 .Nm
-reads numbers, one per line, from standard input, until end of file or error.
+reads numbers, one per line, from standard input until end of file or 0
+is entered or an error occurs.
 Leading white-space and empty lines are ignored.
+.Pp
 Numbers may be preceded by a single
 .Ql + .
+Numbers can be either decimal or hexadecimal strings where the longest
+leading substring is used.
 Numbers are terminated by a non-digit character (such as a newline).
+If the string contains only decimal digits, it is treated as a
+decimal representation for a number.
+A hexadecimal string can contain an optional
+.Em 0x
+or
+.Em 0X
+prefix.
 After a number is read, it is factored.
 .Pp
 The
@@ -89,7 +100,7 @@ The
 value must not be greater than the maximum.
 The default and maximum value of
 .Ar stop
-is 3825123056546413050.
+is 18446744073709551615.
 .Pp
 When the
 .Nm primes

Modified: head/usr.bin/factor/factor.c
==============================================================================
--- head/usr.bin/factor/factor.c	Sun Jan 12 20:19:00 2020	(r356665)
+++ head/usr.bin/factor/factor.c	Sun Jan 12 20:25:11 2020	(r356666)
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
 #include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -97,15 +98,16 @@ typedef u_long	BN_ULONG;
 #define BN_is_one(v)		(*(v) == 1)
 #define BN_mod_word(a, b)	(*(a) % (b))
 
-static int	BN_dec2bn(BIGNUM **a, const char *str);
-static int	BN_hex2bn(BIGNUM **a, const char *str);
+static int	BN_dec2bn(BIGNUM **, const char *);
+static int	BN_hex2bn(BIGNUM **, const char *);
 static BN_ULONG BN_div_word(BIGNUM *, BN_ULONG);
 static void	BN_print_fp(FILE *, const BIGNUM *);
 
 #endif
 
 static void	BN_print_dec_fp(FILE *, const BIGNUM *);
-
+static void	convert_str2bn(BIGNUM **, char *);
+static bool	is_hex_str(char *);
 static void	pr_fact(BIGNUM *);	/* print factors of a value */
 static void	pr_print(BIGNUM *);	/* print a prime */
 static void	usage(void);
@@ -148,21 +150,13 @@ main(int argc, char *argv[])
 			for (p = buf; isblank(*p); ++p);
 			if (*p == '\n' || *p == '\0')
 				continue;
-			if (*p == '-')
-				errx(1, "negative numbers aren't permitted.");
-			if (BN_dec2bn(&val, buf) == 0 &&
-			    BN_hex2bn(&val, buf) == 0)
-				errx(1, "%s: illegal numeric format.", buf);
+			convert_str2bn(&val, p);
 			pr_fact(val);
 		}
 	/* Factor the arguments. */
 	else
-		for (; *argv != NULL; ++argv) {
-			if (argv[0][0] == '-')
-				errx(1, "negative numbers aren't permitted.");
-			if (BN_dec2bn(&val, argv[0]) == 0 &&
-			    BN_hex2bn(&val, argv[0]) == 0)
-				errx(1, "%s: illegal numeric format.", argv[0]);
+		for (p = *argv; p != NULL; p = *++argv) {
+			convert_str2bn(&val, p);
 			pr_fact(val);
 		}
 	exit(0);
@@ -346,7 +340,7 @@ BN_dec2bn(BIGNUM **a, const char *str)
 
 	errno = 0;
 	**a = strtoul(str, &p, 10);
-	return (errno == 0 && (*p == '\n' || *p == '\0'));
+	return (errno == 0 ? 1 : 0);	/* OpenSSL returns 0 on error! */
 }
 
 static int
@@ -356,7 +350,7 @@ BN_hex2bn(BIGNUM **a, const char *str)
 
 	errno = 0;
 	**a = strtoul(str, &p, 16);
-	return (errno == 0 && (*p == '\n' || *p == '\0'));
+	return (errno == 0 ? 1 : 0);	/* OpenSSL returns 0 on error! */
 }
 
 static BN_ULONG
@@ -370,3 +364,46 @@ BN_div_word(BIGNUM *a, BN_ULONG b)
 }
 
 #endif
+
+/*
+ * Scan the string from left-to-right to see if the longest substring
+ * is a valid hexadecimal number.
+ */
+static bool
+is_hex_str(char *str)
+{
+	char c, *p;
+	bool saw_hex = false;
+
+	for (p = str; *p; p++) {
+		if (isdigit(*p))
+			continue;
+		c = tolower(*p);
+		if (c >= 'a' && c <= 'f') {
+			saw_hex = true;
+			continue;
+		}
+		break;	/* Not a hexadecimal digit. */
+	}
+	return saw_hex;
+}
+
+/* Convert string pointed to by *str to a bignum.  */
+static void
+convert_str2bn(BIGNUM **val, char *p)
+{
+	int n = 0;
+
+	if (*p == '+') p++;
+	if (*p == '-')
+		errx(1, "negative numbers aren't permitted.");
+	if (*p == '0') {
+		p++;
+		if (*p == 'x' || *p == 'X')
+			n = BN_hex2bn(val, ++p);
+	} else {
+		n = is_hex_str(p) ? BN_hex2bn(val, p) : BN_dec2bn(val, p);
+	}
+	if (n == 0)
+		errx(1, "%s: illegal numeric format.", p);
+}

Modified: head/usr.bin/primes/primes.c
==============================================================================
--- head/usr.bin/primes/primes.c	Sun Jan 12 20:19:00 2020	(r356665)
+++ head/usr.bin/primes/primes.c	Sun Jan 12 20:25:11 2020	(r356666)
@@ -55,8 +55,8 @@ static const char rcsid[] =
  *	primes [-h] [start [stop]]
  *
  *	Print primes >= start and < stop.  If stop is omitted,
- *	the value 4294967295 (2^32-1) is assumed.  If start is
- *	omitted, start is read from standard input.
+ *	the value 18446744073709551615 (2^64-1) is assumed.  If
+ *	start is omitted, start is read from standard input.
  *
  * validation check: there are 664579 primes between 0 and 10^7
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001122025.00CKPBSW071370>