[PATCH] use-after-free in expand_string_dollar_quote

2023-06-01 Thread Grisha Levit
A use-after-free happens in expand_string_dollar_quote if
noexpand_translation is enabled and a string's translation is the same
length as the string itself.
---
diff --git a/subst.c b/subst.c
index 08d9285e..a7a386d4 100644
--- a/subst.c
+++ b/subst.c
@@ -4231,12 +4231,17 @@ expand_string_dollar_quote (const char
*string, int flags)
  continue;
}
  trans = locale_expand (t, 0, news-sindex, 0, &translen);
- free (t);
  if (singlequote_translations &&
((news-sindex-1) != translen || STREQN (t, trans,
translen) == 0))
-   t = sh_single_quote (trans);
+   {
+ free (t);
+ t = sh_single_quote (trans);
+   }
  else
-   t = sh_mkdoublequoted (trans, translen, 0);
+   {
+ free (t);
+ t = sh_mkdoublequoted (trans, translen, 0);
+   }
  sindex = news;
}
 #endif /* TRANSLATABLE_STRINGS */



set -e not working as expected with conditional operators

2023-06-01 Thread rpaufin1
Consider the following script:

#!/bin/bash

f() {
ls missing-file 2> /dev/null
echo "test"
}

# 1
(set -e; f); ret=$?
if (( ret )); then
echo "failed"
exit 1
fi

# 2
(set -e; f) || {
echo "failed"
exit 1
}

Running the block labelled '1' prints "failed" and returns 1 as the exit code, 
while running the other block prints "test" and returns 0. However, the result 
should be the same.
If f() is modified like so, however:

f() {
ls missing-file 2> /dev/null || return 1
echo "test"
}

then it "works", but this also works without using set -e.

I thought this was an issue with subshells, but apparently the following script 
also doesn't work as expected:

#!/bin/bash

f() {
ls missing-file 2> /dev/null
echo "test"
}

set -e
f && :

Since f() is not ran in a subshell, the script should quit after the 'ls' 
command because of set -e, but "test" is still printed and the script exits 
with 0. To make this script work you can either remove the "&& :" part or the 
'echo' command from f(), but again, it doesn't seem like it's supposed to work 
this way.

# This works
f() {
ls missing-file 2> /dev/null
}
set -e
f && :

# This also works
f() {
ls missing-file 2> /dev/null
echo "test"
}
set -e
f

What's going on here? I'm using the latest release, Bash 5.2.15.