Graphics protocol: Only delete temporary image-data files if they are in a known temporary file location
This commit is contained in:
parent
4a8562a85f
commit
d20c65ef80
@ -201,7 +201,11 @@ Value of `t` Meaning
|
||||
================== ============
|
||||
``d`` Direct (the data is transmitted within the escape code itself)
|
||||
``f`` A simple file
|
||||
``t`` A temporary file, the terminal emulator will delete the file after reading the pixel data
|
||||
``t`` A temporary file, the terminal emulator will delete the file after reading the pixel data. For security reasons
|
||||
the terminal emulator should only delete the file if it
|
||||
is in a known temporary directory, such as :file:`/tmp`,
|
||||
:file:`/dev/shm`, :file:`TMPDIR env var if present` and any platform
|
||||
specific temporary directories.
|
||||
``s`` A `POSIX shared memory object <http://man7.org/linux/man-pages/man7/shm_overview.7.html>`_.
|
||||
The terminal emulator will delete it after reading the pixel data
|
||||
================== ============
|
||||
|
||||
@ -32,9 +32,9 @@ from .rgb import Color, color_from_int
|
||||
from .session import create_session
|
||||
from .tabs import SpecialWindow, SpecialWindowInstance, TabManager
|
||||
from .utils import (
|
||||
get_editor, get_primary_selection, log_error, open_url, parse_address_spec,
|
||||
remove_socket_file, safe_print, set_primary_selection, single_instance,
|
||||
startup_notification_handler
|
||||
get_editor, get_primary_selection, is_path_in_temp_dir, log_error,
|
||||
open_url, parse_address_spec, remove_socket_file, safe_print,
|
||||
set_primary_selection, single_instance, startup_notification_handler
|
||||
)
|
||||
|
||||
|
||||
@ -959,3 +959,7 @@ class Boss:
|
||||
for tm in self.all_tab_managers:
|
||||
tm.tab_bar.patch_colors(spec)
|
||||
patch_global_colors(spec, configured)
|
||||
|
||||
def safe_delete_temp_file(self, path):
|
||||
if is_path_in_temp_dir(path):
|
||||
os.remove(path)
|
||||
|
||||
@ -368,7 +368,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
||||
if (fd == -1) ABRT(EBADF, "Failed to open file %s for graphics transmission with error: [%d] %s", fname, errno, strerror(errno));
|
||||
img->data_loaded = mmap_img_file(self, img, fd, g->data_sz, g->data_offset);
|
||||
close(fd);
|
||||
if (tt == 't') unlink(fname);
|
||||
if (tt == 't') { call_boss(safe_delete_temp_file, "s", fname); }
|
||||
else if (tt == 's') shm_unlink(fname);
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -432,3 +432,20 @@ def get_editor():
|
||||
ans = shlex.split(ans)
|
||||
get_editor.ans = ans
|
||||
return ans
|
||||
|
||||
|
||||
def is_path_in_temp_dir(path):
|
||||
if not path:
|
||||
return False
|
||||
|
||||
def abspath(x):
|
||||
if x:
|
||||
return os.path.abspath(os.path.realpath(x))
|
||||
|
||||
import tempfile
|
||||
path = abspath(path)
|
||||
candidates = frozenset(map(abspath, ('/tmp', '/dev/shm', os.environ.get('TMPDIR', None), tempfile.gettempdir())))
|
||||
for q in candidates:
|
||||
if q and path.startswith(q):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -2,13 +2,16 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from kitty.config import build_ansi_color_table, defaults
|
||||
from kitty.fast_data_types import (
|
||||
REVERSE, ColorProfile, Cursor as C, HistoryBuf, LineBuf,
|
||||
parse_input_from_terminal, wcswidth, wcwidth, truncate_point_for_length
|
||||
parse_input_from_terminal, truncate_point_for_length, wcswidth, wcwidth
|
||||
)
|
||||
from kitty.rgb import to_color
|
||||
from kitty.utils import sanitize_title
|
||||
from kitty.utils import is_path_in_temp_dir, sanitize_title
|
||||
|
||||
from . import BaseTest, filled_cursor, filled_history_buf, filled_line_buf
|
||||
|
||||
@ -384,6 +387,12 @@ class TestDataTypes(BaseTest):
|
||||
tp('a\033', '_', 'x\033', '\\b', text='a b', apc='x')
|
||||
tp('a\033_', 'x', '\033', '\\', 'b', text='a b', apc='x')
|
||||
|
||||
for prefix in ('/tmp', tempfile.gettempdir()):
|
||||
for path in ('a.png', 'x/b.jpg', 'y/../c.jpg'):
|
||||
self.assertTrue(is_path_in_temp_dir(os.path.join(prefix, path)))
|
||||
for path in ('/home/xy/d.png', '/tmp/../home/x.jpg'):
|
||||
self.assertFalse(is_path_in_temp_dir(os.path.join(path)))
|
||||
|
||||
def test_color_profile(self):
|
||||
c = ColorProfile()
|
||||
c.update_ansi_color_table(build_ansi_color_table())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user