commit 27ae6a548a31420c571ee11d199c7625d0e8d731 from: Stefan Sperling via: Thomas Adam date: Thu Nov 14 16:16:05 2024 UTC do not call fmemopen(3) with a zero size argument Calling fmemopen(3) with a size of zero leads to an "Invalid argument" error. One symptom of this issue are failing gotd notifications: gotd[48539]: render notification: fmemopen: Invalid argument Add an email notification test case which triggers the above error. Reported by Mischa Peters commit - daf4cb35f2cef3ba7b74aa8900e9c762e48a32ec commit + 27ae6a548a31420c571ee11d199c7625d0e8d731 blob - ea32f22e2f55de21f40313b7d5bfd7250fb8b166 blob + 7842b10124af03954b75dd4705583bd9b5e1942a --- lib/object_open_io.c +++ lib/object_open_io.c @@ -801,7 +801,7 @@ open_blob(struct got_blob_object **blob, struct got_re goto done; } - if (outbuf) { + if (outbuf && size > 0) { (*blob)->f = fmemopen(outbuf, size, "rb"); if ((*blob)->f == NULL) { err = got_error_from_errno("fmemopen"); blob - 737c3fde2ecd44b03cf457be5b3727221a611dc2 blob + 4bbe7a29455a0d26337c1c4e23d78ebe768bfe41 --- lib/object_open_privsep.c +++ lib/object_open_privsep.c @@ -979,7 +979,7 @@ open_blob(struct got_blob_object **blob, struct got_re goto done; } - if (outbuf) { + if (outbuf && size > 0) { (*blob)->f = fmemopen(outbuf, size, "rb"); if ((*blob)->f == NULL) { err = got_error_from_errno("fmemopen"); blob - 74a0bac7ae7cce3410954539245f192f58869070 blob + 47fa2440bf33ee2aaeb5666989e980ead4619543 --- regress/gotd/email_notification.sh +++ regress/gotd/email_notification.sh @@ -552,7 +552,85 @@ test_tag_changed() { test_done "$testroot" "$ret" } + +test_file_empty() { + local testroot=`test_init file_empty 1` + got clone -a -q ${GOTD_TEST_REPO_URL} $testroot/repo-clone + ret=$? + if [ $ret -ne 0 ]; then + echo "got clone failed unexpectedly" >&2 + test_done "$testroot" 1 + return 1 + fi + + got checkout -q $testroot/repo-clone $testroot/wt >/dev/null + ret=$? + if [ $ret -ne 0 ]; then + echo "got checkout failed unexpectedly" >&2 + test_done "$testroot" 1 + return 1 + fi + + echo -n "" > $testroot/wt/alpha + (cd $testroot/wt && got commit -m 'empty file' > /dev/null) + local commit_id=`git_show_head $testroot/repo-clone` + local author_time=`git_show_author_time $testroot/repo-clone` + + (printf "220\r\n250\r\n250\r\n250\r\n354\r\n250\r\n221\r\n" \ + | timeout 5 nc -l "$GOTD_TEST_SMTP_PORT" > $testroot/stdout) & + + sleep 1 # server starts up + + got send -b main -q -r $testroot/repo-clone + ret=$? + if [ $ret -ne 0 ]; then + echo "got send failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + wait %1 # wait for nc -l + + short_commit_id=`trim_obj_id 12 $commit_id` + HOSTNAME=`hostname` + printf "HELO localhost\r\n" > $testroot/stdout.expected + printf "MAIL FROM:<${GOTD_USER}@${HOSTNAME}>\r\n" \ + >> $testroot/stdout.expected + printf "RCPT TO:<${GOTD_DEVUSER}>\r\n" >> $testroot/stdout.expected + printf "DATA\r\n" >> $testroot/stdout.expected + printf "From: ${GOTD_USER}@${HOSTNAME}\r\n" >> $testroot/stdout.expected + printf "To: ${GOTD_DEVUSER}\r\n" >> $testroot/stdout.expected + printf "Subject: $GOTD_TEST_REPO_NAME: " >> $testroot/stdout.expected + printf "${GOTD_DEVUSER} changed refs/heads/main: $short_commit_id\r\n" \ + >> $testroot/stdout.expected + printf "\r\n" >> $testroot/stdout.expected + printf "commit $commit_id\n" >> $testroot/stdout.expected + printf "from: $GOT_AUTHOR\n" >> $testroot/stdout.expected + d=`date -u -r $author_time +"%a %b %e %X %Y UTC"` + printf "date: $d\n" >> $testroot/stdout.expected + printf "messagelen: 12\n" >> $testroot/stdout.expected + printf " \n" >> $testroot/stdout.expected + printf " empty file\n \n" >> $testroot/stdout.expected + printf " M alpha | 0+ 1-\n\n" >> $testroot/stdout.expected + printf "1 file changed, 0 insertions(+), 1 deletion(-)\n\n" \ + >> $testroot/stdout.expected + printf "\r\n" >> $testroot/stdout.expected + printf ".\r\n" >> $testroot/stdout.expected + printf "QUIT\r\n" >> $testroot/stdout.expected + + grep -v ^Date $testroot/stdout > $testroot/stdout.filtered + cmp -s $testroot/stdout.expected $testroot/stdout.filtered + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout.filtered + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_file_changed run_test test_many_commits_not_summarized @@ -561,3 +639,4 @@ run_test test_branch_created run_test test_branch_removed run_test test_tag_created run_test test_tag_changed +run_test test_file_empty