Your message dated Mon, 18 Mar 2019 21:33:26 +0000
with message-id <e1h5zss-000erq...@fasolo.debian.org>
and subject line Bug#913765: Removed package(s) from unstable
has caused the Debian Bug report #845397,
regarding Leafpad: mishandling of error cases in the saving function can lead 
to silent data loss
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
845397: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=845397
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: leafpad
Version: 0.8.18.1-5

X-Debbugs-CC: bladeboy200...@gmail.com
Severity: critical

Some mishandling of error return code in the saving function of
leafpad can lead to data loss.


When a file ($FILE) is saved in leafpad, it calls the functions
file_save_real(file.c:180):
 - The content on the GtkTextBuffer is transformed in a gchar*,
 - Then the file $FILE is opened (file.c:220) in write mode (which
truncate $FILE content)
 - The gchar* is written to $FILE (file.c:226) but not necessary yet flushed
   (on my computer there is an autoflush only if more than 4k of data),
 - Leafpad calls the function gtk_text_buffer_set_modified()
(file.c:232) for the UI layer
 - Then the $FILE is closed (file.c:233) which causes the unflushed
content to be finally written to disk.
 - Sadly the result of that fclose() (file.c:233) is not checked at all.

---

1) first problem, the "truncating side-effect"

The call to gtk_text_buffer_set_modified() (file.c:232) triggers a
"modified-changed" signal.
There is a callback (view.c:354) that links that "modified-changed"
signal to cb_modified_changed.
 -> the function cb_modified_changed(view.c:218) calls (view.c:224)
the function get_file_basename()
  -> the function get_file_basename(file.c:42) calls (file.c:66) the
function check_file_writable()
   -> the function check_file_writable(file.c:31) :
     - calls (file.c:35) the function fopen() on the same $FILE in
APPEND mode to check if it's writable
     - and (file.c:36) that second handle on $FILE is closed

Because in the file_save_real(file.c:180), gtk_text_buffer_set_modified()
is called before the fclose() somehow 2 handles on $FILE exists at the
same time,
the second handle being closed before the first.

On a local filesystem (ext4) it usually behave somehow without errors:
when the file is fclosed any unflushed content is then written on disk.

Here is the strace when trying to save 2 bytes in /tmp/file.txt (an
ext filesystem)

file.c:220:file_save_real()      | open("/tmp/file.txt",
O_WRONLY|O_CREAT|O_TRUNC, 0666) = 13
file.c:035:check_file_writable() | open("/tmp/file.txt",
O_WRONLY|O_CREAT|O_APPEND, 0666) = 14
file.c:036:check_file_writable() | close(14)                    = 0
file.c:233:file_save_real()      | *write(13, "X!", 2)           = 2* 🗸
file.c:233:file_save_real()      | close(13)                    = 0

Until here it seems fine,
but that can have a dramatic side-effect when used with gvfs over
sftp, a bug happens!
( see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=680418
and https://bugs.launchpad.net/ubuntu/+source/leafpad/+bug/708829 )

gfvs+sftp don't like having concurrently 2 file pointers on the same file,
and trying to write data on the oldest, after having closed the
youngest ... fails and the file end up truncated.

After having mounted the sftp://localhost/tmp/file.txt via gvfs, the same strace

file.c:220:file_save_real()      |
open("/run/user/1000/gvfs/sftp:host=localhost,user=me/tmp/file.txt",
O_WRONLY|O_CREAT|O_TRUNC, 0666) = 13
file.c:035:check_file_writable() |
open("/run/user/1000/gvfs/sftp:host=localhost,user=me/tmp/file.txt",
O_WRONLY|O_CREAT|O_APPEND, 0666) = 14
file.c:036:check_file_writable() | close(14)                    = 0
file.c:233:file_save_real()      | *write(13, "X!", 2)           = -1
EOPNOTSUPP (Operation not supported) 🗴 *😱
file.c:233:file_save_real()      | close(13)                    = 0

Solution proposed:
        As previously proposed in 2012 (and by Max Rockatanski
<bladeboy200...@gmail.com> in 2016) on bug=680418,
        the call to fclose() should be done before the call to
gtk_text_buffer_set_modified().

        The data should also probably be fflushed and fsynced just after the 
fwrite.

---

2) second problem, the silent (No space left on device)

The result of fclose() (file.c:233) being not checked at all,
if there is not enough space on disk to write data when flushing, the
remaining data is currently silently lost.
For example try creating a ram drive of 4kb:
        mkdir -p /tmp/tmpfs4k && mount -o size=4k -t tmpfs none /tmp/tmpfs4k

Then try to write 4097 bytes into /tmp/tmpfs4k/test (with a strace) :

file.c:220:file_save_real()      | open("/tmp/tmpfs4k/test",
O_WRONLY|O_CREAT|O_TRUNC, 0666) = 13
file.c:226:file_save_real()      | write(13,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"..., 4096) = 4096
file.c:035:check_file_writable() | open("/tmp/tmpfs4k/test",
O_WRONLY|O_CREAT|O_APPEND, 0666) = 14
file.c:036:check_file_writable() | close(14)                    = 0
file.c:233:file_save_real()      | *write(13, "!", 1)            = -1
ENOSPC (No space left on device) 🗴 😱*
file.c:233:file_save_real()      | close(13)                    = 0

Solution proposed:
        The return code for fopen should be checked and a feedback should be
provided to the user if an error occur.
        (and the same thing should be done if we add a fflush and a fsync)

--- End Message ---
--- Begin Message ---
Version: 0.8.18.1-5+rm

Dear submitter,

as the package leafpad has just been removed from the Debian archive
unstable we hereby close the associated bug reports.  We are sorry
that we couldn't deal with your issue properly.

For details on the removal, please see https://bugs.debian.org/913765

The version of this package that was in Debian prior to this removal
can still be found using http://snapshot.debian.org/.

This message was generated automatically; if you believe that there is
a problem with it please contact the archive administrators by mailing
ftpmas...@ftp-master.debian.org.

Debian distribution maintenance software
pp.
Scott Kitterman (the ftpmaster behind the curtain)

--- End Message ---

Reply via email to