public inbox for libc-help@sourceware.org
 help / color / mirror / Atom feed
* strtol(3) setting of errno
@ 2023-11-30  9:22 Alejandro Colomar
  2023-11-30 12:00 ` Florian Weimer
  0 siblings, 1 reply; 5+ messages in thread
From: Alejandro Colomar @ 2023-11-30  9:22 UTC (permalink / raw)
  To: GNU C Library, Linux man-pages; +Cc: Iker Pedrosa, shadow, Michael Kerrisk

[-- Attachment #1: Type: text/plain, Size: 3470 bytes --]

Hi,

We were discussing a use of strtol(3) in shadow-utils, and after reading
strtol(3) several times, I'm not sure about the exact interface of the
function.

Normally, libc functions are allowed to set errno on success, and a
caller should not inspect errno, even if it was set to 0 prior to the
call, unless the function reported an error via the return value.

However, strtol(3) is a bit special, in that it's one of the few libc
functions that report an error with a return value that is also in the
range of valid return values of the function.

So, here's how I understand the function works:

-  If the base is unsupported, return 0, and set errno to EINVAL.  Let's
   ignore this error for the rest of the question, since usually you set
   the base to something common, likely 0 or 10.

-  If no digits were found (no conversion is performed), return 0, set
   *endptr == str, and possibly set errno to EINVAL (setting errno is
   allowed but not required).

-  If the conversion would have overflowed, return LONG_MAX, and set
   errno to ERANGE.
-  If the conversion would have underflowed, return LONG_MIN, and set
   errno to ERANGE.

-  If the conversion succeeded, return the value, which may or may not
   be 0, LONG_MIN, or LONG_MAX.  And the question here is: is there any
   guarantee that strtol(3) won't set errno in this case?

I ask because the manual page says:

NOTES
     Since  strtol()  can legitimately return 0, LONG_MAX, or LONG_MIN
     (LLONG_MAX or LLONG_MIN for strtoll()) on both success and  fail‐
     ure,  the  calling program should set errno to 0 before the call,
     and then determine if an error occurred by checking whether errno
     has a nonzero value after the call.

And then in EXAMPLES:

         val = strtol(str, &endptr, base);

         /* Check for various possible errors. */

         if (errno != 0) {
             perror("strtol");
             exit(EXIT_FAILURE);
         }

         if (endptr == str) {
             fprintf(stderr, "No digits were found\n");
             exit(EXIT_FAILURE);
         }

         /* If we got here, strtol() successfully parsed a number. */

Which is consistent with a possible interpretation of what NOTES says,
but I think that may be because it is a bit ambiguous.  The example
program is my fault, because I changed that code:

	commit 93f369892aeab4d56b92962224e318f739ee2455
	Author: Alejandro Colomar <colomar.6.4.3@gmail.com>
	Date:   Wed Oct 28 10:33:08 2020 +0100

	    strtol.3: EXAMPLES: Simplify errno checking
	    
	    (No expected change in behavior,)
	    
	    Signed-off-by: Alejandro Colomar <colomar.6.4.3@gmail.com>
	    Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>

	diff --git a/man3/strtol.3 b/man3/strtol.3
	index a436bcac4..3889ef6b5 100644
	--- a/man3/strtol.3
	+++ b/man3/strtol.3
	@@ -276,8 +276,7 @@ .SS Program source
	 
	     /* Check for various possible errors */
	 
	-    if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
	-            || (errno != 0 && val == 0)) {
	+    if (errno != 0) {
		 perror("strtol");
		 exit(EXIT_FAILURE);
	     }

Now I realize that commit was probably wrong, and one needs to check
both errno and the return value to determine that the call failed.  Can
you please confirm what the correct specification of strtol(3) is?

Thanks,
Alex

-- 
<https://www.alejandro-colomar.es/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: strtol(3) setting of errno
  2023-11-30  9:22 strtol(3) setting of errno Alejandro Colomar
@ 2023-11-30 12:00 ` Florian Weimer
  2023-11-30 12:40   ` Alejandro Colomar
  0 siblings, 1 reply; 5+ messages in thread
From: Florian Weimer @ 2023-11-30 12:00 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: GNU C Library, Linux man-pages, Iker Pedrosa, shadow, Michael Kerrisk

* Alejandro Colomar:

> Now I realize that commit was probably wrong, and one needs to check
> both errno and the return value to determine that the call failed.  Can
> you please confirm what the correct specification of strtol(3) is?

The most detailed specification we have is the one that is in POSIX.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: strtol(3) setting of errno
  2023-11-30 12:00 ` Florian Weimer
@ 2023-11-30 12:40   ` Alejandro Colomar
  2023-11-30 22:13     ` Jakub Wilk
  0 siblings, 1 reply; 5+ messages in thread
From: Alejandro Colomar @ 2023-11-30 12:40 UTC (permalink / raw)
  To: Florian Weimer
  Cc: GNU C Library, Linux man-pages, Iker Pedrosa, shadow, Michael Kerrisk

[-- Attachment #1: Type: text/plain, Size: 826 bytes --]

Hi Florian,

On Thu, Nov 30, 2023 at 01:00:30PM +0100, Florian Weimer wrote:
> * Alejandro Colomar:
> 
> > Now I realize that commit was probably wrong, and one needs to check
> > both errno and the return value to determine that the call failed.  Can
> > you please confirm what the correct specification of strtol(3) is?
> 
> The most detailed specification we have is the one that is in POSIX.

Since POSIX doesn't specify, I assume it allows setting errno on
success, as with any other libc function.  That includes setting errno
on a successful call that returns 0.  Which means that the errno check
must check for the specific errno values that actually mean an error of
this function.

I'll update the page.

Thanks,
Alex

> 
> Thanks,
> Florian
> 

-- 
<https://www.alejandro-colomar.es/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: strtol(3) setting of errno
  2023-11-30 12:40   ` Alejandro Colomar
@ 2023-11-30 22:13     ` Jakub Wilk
  2023-11-30 22:45       ` Alejandro Colomar
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Wilk @ 2023-11-30 22:13 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: Florian Weimer, libc-help, linux-man, Iker Pedrosa,
	~hallyn/shadow, Michael Kerrisk

* Alejandro Colomar <alx@kernel.org>, 2023-11-30 13:40:
>Since POSIX doesn't specify, I assume it allows setting errno on 
>success, as with any other libc function.  That includes setting errno 
>on a successful call that returns 0.

No? "These functions shall not change the setting of errno if 
successful."

-- 
Jakub Wilk

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: strtol(3) setting of errno
  2023-11-30 22:13     ` Jakub Wilk
@ 2023-11-30 22:45       ` Alejandro Colomar
  0 siblings, 0 replies; 5+ messages in thread
From: Alejandro Colomar @ 2023-11-30 22:45 UTC (permalink / raw)
  To: Jakub Wilk
  Cc: Florian Weimer, libc-help, linux-man, Iker Pedrosa,
	~hallyn/shadow, Michael Kerrisk

[-- Attachment #1: Type: text/plain, Size: 610 bytes --]

Hi Jakub,

On Thu, Nov 30, 2023 at 11:13:01PM +0100, Jakub Wilk wrote:
> * Alejandro Colomar <alx@kernel.org>, 2023-11-30 13:40:
> > Since POSIX doesn't specify, I assume it allows setting errno on
> > success, as with any other libc function.  That includes setting errno
> > on a successful call that returns 0.
> 
> No? "These functions shall not change the setting of errno if successful."

Ahhh, I missed that text.  Thanks!  It means that a simple errno!=0 is
enough (plus the endptr check), then, and the current page is correct.

Cheers,
Alex

-- 
<https://www.alejandro-colomar.es/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-11-30 22:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-30  9:22 strtol(3) setting of errno Alejandro Colomar
2023-11-30 12:00 ` Florian Weimer
2023-11-30 12:40   ` Alejandro Colomar
2023-11-30 22:13     ` Jakub Wilk
2023-11-30 22:45       ` Alejandro Colomar

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 read-only IMAP folder(s) and NNTP newsgroup(s).