lcompilers / lpython

Python compiler
https://lpython.org/
Other
1.37k stars 157 forks source link

Bug: Segmentation Fault while looping through a `for...in` loop on a `ConstantList` or `StringConstant` or subscripts of the same #2608

Closed kmr-srbh closed 2 months ago

kmr-srbh commented 3 months ago

Example 1

from lpython import i32, list
i: i32
for i in [1, 2, 3, 4, 5]:
    print(i)

Example 2

from lpython import i32, list

i: i32
l: list[i32] = [1, 2, 3, 4]
for i in l[1:3]:
    print(i)

The same is true for a StringConstant.

Stacktrace

(base) saurabh-kumar@Awadh:~/Projects/System/lpython$ ./src/bin/lpython ./examples/example.py
Traceback (most recent call last):
  Binary file "/home/saurabh-kumar/Projects/System/lpython/src/bin/lpython", in _start()
  File "./csu/../csu/libc-start.c", line 360, in __libc_start_main_impl()
  File "./csu/../sysdeps/x86/libc-start.c", line 58, in __libc_start_call_main()
  File "/home/saurabh-kumar/Projects/System/lpython/src/bin/lpython.cpp", line 1932, in main()
    err = compile_python_to_object_file(arg_file, tmp_o, runtime_library_dir,
  File "/home/saurabh-kumar/Projects/System/lpython/src/bin/lpython.cpp", line 838, in compile_python_to_object_file()
    !(arg_c && compiler_options.po.disable_main), "__main__", infile);
  File "/home/saurabh-kumar/Projects/System/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 8150, in LCompilers::LPython::python_ast_to_asr(Allocator&, LCompilers::LocationManager&, LCompilers::SymbolTable*, LCompilers::LPython::AST::ast_t&, LCompilers::diag::Diagnostics&, LCompilers::CompilerOptions&, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)
    ast_overload, allow_implicit_casting);
  File "/home/saurabh-kumar/Projects/System/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 8087, in LCompilers::LPython::body_visitor(Allocator&, LCompilers::LocationManager&, LCompilers::LPython::AST::Module_t const&, LCompilers::diag::Diagnostics&, LCompilers::ASR::asr_t*, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<int, LCompilers::ASR::symbol_t*, std::less<int>, std::allocator<std::pair<int const, LCompilers::ASR::symbol_t*> > >&, bool)
    b.visit_Module(ast);
  File "/home/saurabh-kumar/Projects/System/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 4732, in LCompilers::LPython::BodyVisitor::visit_Module(LCompilers::LPython::AST::Module_t const&)
    visit_stmt(*x.m_body[i]);
  File "/home/saurabh-kumar/Projects/System/lpython/src/lpython/python_ast.h", line 1883, in LCompilers::LPython::AST::BaseVisitor<LCompilers::LPython::BodyVisitor>::visit_stmt(LCompilers::LPython::AST::stmt_t const&)
    void visit_stmt(const stmt_t &b) { visit_stmt_t(b, self()); }
  File "/home/saurabh-kumar/Projects/System/lpython/src/lpython/python_ast.h", line 1759, in visit_stmt_t<LCompilers::LPython::BodyVisitor>()
    case stmtType::For: { v.visit_For((const For_t &)x); return; }
  File "/home/saurabh-kumar/Projects/System/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 5477, in LCompilers::LPython::BodyVisitor::visit_For(LCompilers::LPython::AST::For_t const&)
    current_body->push_back(al, ASRUtils::STMT(assign));
  File "/home/saurabh-kumar/Projects/System/lpython/src/libasr/containers.h", line 110, in LCompilers::Vec<LCompilers::ASR::stmt_t*>::push_back(Allocator&, LCompilers::ASR::stmt_t*)
    LCOMPILERS_ASSERT(reserve_called == vec_called_const);
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", in __GI___sigaction()
Segfault: Signal SIGSEGV (segmentation fault) received
kmr-srbh commented 2 months ago

This is actually a bug related to the variable scope. When creating a variable for the ConstantList to loop on, the variable scope is set to local. The above example, being in a global scope, fails but those in a local scope work as intended.

from lpython import i32

def foo():
    i: i32
    for i in [1, 2, 3, 4, 5]:
        print(i)

foo()
(base) saurabh-kumar@Awadh:~/Projects/System/lpython$ ./src/bin/lpython ./examples/example.py
1
2
3
4
5
tanay-man commented 2 months ago

The offending line is current_body->push_back(al, ASRUtils::STMT(assign));

In case of global scope, the current_body pointer is a null pointer and hence the seg fault occurs by dereferencing it. Afaik current_body points to a list of statements in the current scope, and it is written in its documentation that it exists only for Functions, For etc and not Modules, ClassDefs/Structs.

@kmr-srbh if you know the equivalent for current_body for the module, it is an easy fix. I am unaware of the same.

tanay-man commented 2 months ago

The fix was very simple we just had to use global_init when currrent_body doesnt exist.