Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guard against FileNotFoundError #227

Closed
wants to merge 1 commit into from
Closed

Guard against FileNotFoundError #227

wants to merge 1 commit into from

Conversation

rixx
Copy link

@rixx rixx commented Nov 29, 2017

I ran into this issue in production – os.getcwd() may raise a FileNotFoundError.

@asottile
Copy link
Member

python2+python3 compatibility: should use OSError:

$ mkdir foo && bash -c "cd foo && rmdir ../foo && python -c 'import os; os.getcwd()'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
OSError: [Errno 2] No such file or directory
$ mkdir foo && bash -c "cd foo && rmdir ../foo && python3 -c 'import os; os.getcwd()'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory
$ python3 -c 'print(issubclass(FileNotFoundError, OSError))'
True

sass.py Outdated
@@ -50,6 +50,9 @@
#: (:class:`collections.Set`) The set of keywords :func:`compile()` can take.
MODES = set(['string', 'filename', 'dirname'])

if PY2:
FileNotFoundError = OSError

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of this, just use OSError in the except block

@rixx
Copy link
Author

rixx commented Nov 29, 2017

@asottile Yeah, I noticed the failing tests – updated as per your preference.

# #208: cwd is always included in include paths, if possible
try:
include_paths = (os.getcwd(),)
except OSError:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth calling out why this OSError can occur, perhaps something like: "if the current working directory has been deleted, getcwd() will raise"

might also be good to write a quick regression test to demonstrate this -- let me know if you'd like some help with this -- it should be pretty easy to start with something like this:

def test_compile_in_missing_dir(tmpdir):
    does_not_exist = tmpdir.join('does_not_exist').ensure_dir()
    with does_not_exist.as_cwd():
        does_not_exist.remove()
        # run a compile from here

@asottile
Copy link
Member

asottile commented Dec 2, 2017

I actually tried writing such a test, I'm not sure this ever worked:

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
============================= test session starts ==============================
platform linux -- Python 3.6.3, pytest-3.3.0, py-1.5.2, pluggy-0.6.0
rootdir: /tmp/libsass-python, inifile:
collected 91 items                                                             

sasstests.py ........................................................... [ 64%]
...............................
Program received signal SIGABRT, Aborted.
0x00007ffff6cd2428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
54	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) where
#0  0x00007ffff6cd2428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff6cd402a in __GI_abort () at abort.c:89
#2  0x00007ffff2c7184d in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff2c6f6b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff2c6f701 in std::terminate() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff2c6f919 in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff2c9814f in std::__throw_logic_error(char const*) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff30d3044 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*> (
    this=this@entry=0xfd3a68, __beg=__beg@entry=0x0, __end=<optimized out>)
    at /usr/include/c++/5/bits/basic_string.tcc:216
#8  0x00007ffff30d313e in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct_aux<char const*> (
    __end=<optimized out>, __beg=0x0, this=0xfd3a68)
    at /usr/include/c++/5/bits/basic_string.h:195
#9  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*> (__end=<optimized out>, __beg=0x0, 
    this=0xfd3a68) at /usr/include/c++/5/bits/basic_string.h:214
#10 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__a=..., __s=0x0, this=0xfd3a68)
    at /usr/include/c++/5/bits/basic_string.h:456
#11 Sass::File::get_cwd[abi:cxx11]() () at libsass/src/file.cpp:58
#12 0x00007ffff3063908 in Sass::Context::Context (this=0xfd3a60, c_ctx=...)
    at libsass/src/context.cpp:89
#13 0x00007ffff3179ee8 in Sass::File_Context::File_Context (ctx=..., 
    this=0xfd3a60) at libsass/src/context.hpp:125
#14 sass_compile_file_context (file_ctx=file_ctx@entry=0xfd4770)
    at libsass/src/sass_context.cpp:462
#15 0x00007ffff318bb77 in PySass_compile_filename (self=<optimized out>, 
    args=<optimized out>) at pysass.cpp:592
#16 0x00000000004b34b9 in _PyCFunction_FastCallKeywords ()
#17 0x0000000000544e1e in ?? ()
#18 0x0000000000546e9d in _PyEval_EvalFrameDefault ()
#19 0x0000000000544a85 in ?? ()
#20 0x0000000000544d37 in ?? ()
#21 0x0000000000546b0b in _PyEval_EvalFrameDefault ()
#22 0x0000000000544a85 in ?? ()
#23 0x000000000054599e in PyEval_EvalCodeEx ()
#24 0x0000000000489dd6 in ?? ()
#25 0x0000000000456d9c in PyObject_Call ()
#26 0x0000000000548b9a in _PyEval_EvalFrameDefault ()
#27 0x0000000000544a85 in ?? ()
#28 0x000000000054599e in PyEval_EvalCodeEx ()
---Type <return> to continue, or q <return> to quit---Quit

@rixx
Copy link
Author

rixx commented Dec 2, 2017

So how do you want to proceed?

@asottile
Copy link
Member

asottile commented Dec 2, 2017

I like the patch, I'm going to try and fix this upstream as well: sass/libsass#2513

@asottile
Copy link
Member

asottile commented Dec 2, 2017

It may also be time for us to ditch the 3.4.x releases and move to the 3.5 betas -- even though they're "beta"

@rixx
Copy link
Author

rixx commented Feb 10, 2018

Any news on this?

@asottile
Copy link
Member

Yes! Upstream merged a change related to this -- though it still crashes just in a different way now:

Program received signal SIGABRT, Aborted.
0x00007ffff7825428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
54	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7825428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff782702a in __GI_abort () at abort.c:89
#2  0x00007ffff473a84d in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff47386b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff4738701 in std::terminate() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff4738919 in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff4baa8a3 in Sass::File::get_cwd () at libsass/src/file.cpp:59
#7  0x00007ffff4b394fe in Sass::Context::Context (this=0x2757bc0, c_ctx=...)
    at libsass/src/context.cpp:89
#8  0x00007ffff4c5eba8 in Sass::File_Context::File_Context (ctx=..., 
    this=0x2757bc0) at libsass/src/context.hpp:125
#9  sass_compile_file_context (file_ctx=0x274eac0)
    at libsass/src/sass_context.cpp:473
#10 0x00007ffff4c7348b in PySass_compile_filename (self=<optimized out>, 
    args=<optimized out>) at pysass.cpp:592

Here's the full test I'm using:

import sass


def test_compile_in_missing_dir(tmpdir):
    f = tmpdir.join('f.scss')
    f.write('a{color: red;}')
    dne = tmpdir.join('does_not_exist').ensure_dir()
    with dne.as_cwd():
        dne.remove()
        sass.compile(filename=str(f))

Looking back at previous versions, it seems this has never worked though:

0.13.2 - 0.13.7 have the OSError, putting in the try: except: causes them to fail in this way:

(gdb) bt
#0  0x00007ffff7825428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff782702a in __GI_abort () at abort.c:89
#2  0x00007ffff474484d in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff47426b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff4742701 in std::terminate() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff4742919 in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff476b14f in std::__throw_logic_error(char const*) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff4b5bab1 in std::string::_S_construct<char const*> (__beg=0x0, 
    __end=<optimized out>, __a=...)
    at /opt/rh/devtoolset-2/root/usr/include/c++/4.8.2/bits/basic_string.tcc:133
#8  0x00007ffff4785d16 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x00007ffff4afec40 in Sass::File::get_cwd () at libsass/src/file.cpp:57
#10 0x00007ffff4bf443e in Sass::Context::Context (this=0x27551a0, c_ctx=...)
    at libsass/src/context.cpp:89
#11 0x00007ffff4c41b88 in Sass::File_Context::File_Context (ctx=..., 
    this=0x27551a0) at libsass/src/context.hpp:125
#12 sass_compile_file_context (file_ctx=0x2721050)
    at libsass/src/sass_context.cpp:462
#13 0x00007ffff4afe56b in PySass_compile_filename (self=<optimized out>, 
    args=<optimized out>) at pysass.cpp:592

0.13.1 and 0.13.0 and 0.12.3 crash in the same way

Even against the beta (which removes cwd from the search path):

(gdb) bt
#0  0x00007ffff7825428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff782702a in __GI_abort () at abort.c:89
#2  0x00007ffff41ff84d in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff41fd6b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff41fd701 in std::terminate() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff41fd919 in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff4664761 in Sass::File::get_cwd[abi:cxx11]() ()
    at libsass/src/file.cpp:59
#7  0x00007ffff45f3ee9 in Sass::Context::Context (this=0x276fa40, c_ctx=...)
    at libsass/src/context.cpp:89
#8  0x00007ffff4718428 in Sass::File_Context::File_Context (ctx=..., 
    this=0x276fa40) at libsass/src/context.hpp:125
#9  sass_compile_file_context (file_ctx=file_ctx@entry=0x27d8510)
    at libsass/src/sass_context.cpp:473
#10 0x00007ffff472c617 in PySass_compile_filename (self=<optimized out>, 
    args=<optimized out>) at pysass.cpp:597

So I think it's safe to say this never worked, and never will work :(

@rixx
Copy link
Author

rixx commented Feb 10, 2018

Strange, because for me it worked as long as I pinned libsass to 0.13.1 …

@asottile
Copy link
Member

0.13.1 uses libsass 3.4.5

This line is going to crash if pwd is missing: https://github.com/sass/libsass/blob/3.4.5/src/context.cpp#L63

@rixx rixx closed this Jun 22, 2018
@rixx rixx deleted the cwd branch June 22, 2018 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants