Bug 25195 - localedef does not return error status when warnings were issued.
Summary: localedef does not return error status when warnings were issued.
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: locale (show other bugs)
Version: 2.29
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-11-15 22:16 UTC by Sergei Trofimovich
Modified: 2020-02-19 15:24 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sergei Trofimovich 2019-11-15 22:16:40 UTC
The bug was originally discovered in https://bugs.gentoo.org/697908 by Chris Slycord. There we ended up passing invalid charset (with trailing '\r') to localedef. Here is the reproducer:

"""
# /usr/bin/localedef -c --no-archive -i en_US -f $'ISO-8859-1\r' -A /usr/share/locale/locale.alias --prefix / en_US |& cat -v
failed to set locale!
[error] character map file `ISO-8859-1^M' not found: No such file or directory

# echo $?
0
"""

'man localedef' says:

"""
    EXIT STATUS
       One of the following exit values can be returned by localedef:
          0         Command completed successfully.
          1         Warnings or errors occurred, output files were written.
          4         Errors encountered, no output created.
"""

I'm not sure if output was created but the '[error]' warning (or error?) was issued.

I think the exit status should be non-zero.
Comment 2 Carlos O'Donell 2019-11-16 00:43:00 UTC
(In reply to Sergei Trofimovich from comment #0)
> """
> # /usr/bin/localedef -c --no-archive -i en_US -f $'ISO-8859-1\r' -A
> /usr/share/locale/locale.alias --prefix / en_US |& cat -v
> failed to set locale!
> [error] character map file `ISO-8859-1^M' not found: No such file or
> directory
> 
> # echo $?
> 0
> """

You ran two commands. The $? is the exit code of the second command in the pipe. The exit code of cat was 0 (success) which is expected.

If you run just the localedef command:

/usr/bin/localedef -c --no-archive -i en_US -f 'ISO-8859-1\r' -A /usr/share/locale/locale.alias --prefix / en_US
[error] character map file `ISO-8859-1\r' not found: No such file or directory
[error] cannot write output files to `//usr/lib/locale/en_US/': Permission denied
echo $?
4

You get output 4 as expected because errors were encountered and no output was created.

Note: I removed the '$' in front of the charmap because it doesn't seem to apply to the example you were trying to create.

Does the above explain why you see an exit code of zero from the last command in the pipe sequence?

In Bash you can use PIPESTATUS to review the exit status of processes in the last executed foreground pipeline.
Comment 3 Carlos O'Donell 2019-11-16 00:48:41 UTC
(In reply to Carlos O'Donell from comment #2)
> Note: I removed the '$' in front of the charmap because it doesn't seem to
> apply to the example you were trying to create.

Sorry, forgot this was ANSI-C quoting.
Comment 4 Sergei Trofimovich 2019-11-16 11:14:53 UTC
(In reply to Carlos O'Donell from comment #2)
> (In reply to Sergei Trofimovich from comment #0)
> > """
> > # /usr/bin/localedef -c --no-archive -i en_US -f $'ISO-8859-1\r' -A
> > /usr/share/locale/locale.alias --prefix / en_US |& cat -v
> > failed to set locale!
> > [error] character map file `ISO-8859-1^M' not found: No such file or
> > directory
> > 
> > # echo $?
> > 0
> > """
> 
> You ran two commands. The $? is the exit code of the second command in the
> pipe. The exit code of cat was 0 (success) which is expected.

Ah, my apologies for confusion. I tested the command before adding 'cat' for escaping. Here is to original breakage:

  # /usr/bin/localedef -c --no-archive -i en_US -f $'ISO-8859-1\r' -A /usr/share/locale/locale.alias --prefix / en_US; echo $?
  failed to set locale!
  ' not found: No such file or directory
  0

> If you run just the localedef command:
> 
> /usr/bin/localedef -c --no-archive -i en_US -f 'ISO-8859-1\r' -A
> /usr/share/locale/locale.alias --prefix / en_US
> [error] character map file `ISO-8859-1\r' not found: No such file or
> directory
> [error] cannot write output files to `//usr/lib/locale/en_US/': Permission
> denied
> echo $?
> 4

I think you have a different, permission-related problem here.

(In reply to Carlos O'Donell from comment #3)
> (In reply to Carlos O'Donell from comment #2)
> > Note: I removed the '$' in front of the charmap because it doesn't seem to
> > apply to the example you were trying to create.
> 
> Sorry, forgot this was ANSI-C quoting.

'\r' just makes the output most confusing :) Looks like it can be reproduced by any invalid sharset name:

# /usr/bin/localedef -c --no-archive -i en_US -f 'ISO-8859-1-whee' -A /usr/share/locale/locale.alias --prefix / en_US; echo $?
failed to set locale!
[error] character map file `ISO-8859-1-whee' not found: No such file or directory
0
Comment 5 Carlos O'Donell 2019-11-21 04:31:07 UTC
(In reply to Sergei Trofimovich from comment #4)
> # /usr/bin/localedef -c --no-archive -i en_US -f 'ISO-8859-1-whee' -A
> /usr/share/locale/locale.alias --prefix / en_US; echo $?
> failed to set locale!
> [error] character map file `ISO-8859-1-whee' not found: No such file or
> directory
> 0

Thanks, that helped!

cd $HOME
mkdir -p usr/lib/locale/en_US
/usr/bin/localedef -c --no-archive -i en_US \
  -f 'ISO-8859-1-whee' -A /usr/share/locale/locale.alias \
  --prefix $HOME en_US
[error] character map file `ISO-8859-1-whee' not found: No such file or directory
echo $?
0

Reproduced.

This is the expected behaviour. Sorry I didn't notice the "-c" originally.

(a) You specified "-c" on the command line which means "--force" and so regardless of errors the output is written.

(b) If output is written then an error code of 4 cannot be returned. That would violate the POSIX specification e.g. exit code of >= 3 means warnings or errors occurred and _no output_ was generated.

By using "-c" you are basically saying "ignore errors, and force the output" and so the output is generated regardless of the error and that operation as you requested was successful.

Removing "-c" avoids output and returns error code 4.

/usr/bin/localedef --no-archive -i en_US \
  -f 'ISO-8859-1-whee' -A /usr/share/locale/locale.alias \
  --prefix $HOME en_US
[error] character map file `ISO-8859-1-whee' not found: No such file or directory
[error] no output file produced because errors were issued
echo $?
4

I'm marking this RESOLVED/INVALID.

Please reopen if you have any more questions.
Comment 6 Sergei Trofimovich 2019-11-21 07:27:58 UTC
Oh, thank you! We'll try to drop -c.