diff --git a/changelogs/unreleased/gh-6817-console-memory-leak.md b/changelogs/unreleased/gh-6817-console-memory-leak.md new file mode 100644 index 0000000000000000000000000000000000000000..6075cdaa4e726c8f583f715b9c7e321afd6d9d97 --- /dev/null +++ b/changelogs/unreleased/gh-6817-console-memory-leak.md @@ -0,0 +1,3 @@ +## bugfix/core + +* Fixed memory leak in interactive console (gh-6817). diff --git a/src/box/lua/console.c b/src/box/lua/console.c index d9622f3fc5d8ca0dd95b318d4e9fa97353a35afd..db19611a6fa20d2a0deca439cff3a1744c53edb0 100644 --- a/src/box/lua/console.c +++ b/src/box/lua/console.c @@ -223,6 +223,7 @@ console_push_line(char *line) */ rl_callback_handler_install(NULL, NULL); #endif + free(line); } /* implements readline() Lua API */ diff --git a/test/app-luatest/gh_6817_console_memory_leak_test.lua b/test/app-luatest/gh_6817_console_memory_leak_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..c09ef5bf6b3b8bec40800457e17d33ba36253967 --- /dev/null +++ b/test/app-luatest/gh_6817_console_memory_leak_test.lua @@ -0,0 +1,45 @@ +local console = require('console') +local ffi = require('ffi') +local fiber = require('fiber') +local t = require('luatest') +local g = t.group() + +ffi.cdef([[ + int pipe(int pipefd[2]); + int dup2(int oldfd, int newfd); + ssize_t write(int fd, const void *buf, size_t count); + int close(int fd); +]]) + +g.before_test('test_console_mem_leak', function() + -- Replace stdin fd with a pipe fd so that we can emulate user input. + local fd = ffi.new([[ int[2] ]]) + assert(ffi.C.pipe(fd) == 0) + if fd[0] ~= 0 then + assert(ffi.C.dup2(fd[0], 0) == 0) + assert(ffi.C.close(fd[0]) == 0) + end + g.console_write_fd = fd[1] + g.console_write = function(command) + ffi.C.write(g.console_write_fd, command, string.len(command)) + end +end) + +g.after_test('test_console_mem_leak', function() + assert(ffi.C.close(g.console_write_fd) == 0) + assert(ffi.C.close(0) == 0) + g.console_write = nil + g.console_write_fd = nil +end) + +-- Checks that ASAN doesn't detect any memory leaks when console is used. +g.test_console_mem_leak = function() + local on_stop = fiber.channel() + fiber.create(function() + console.start() + on_stop:put(true) + end) + g.console_write('\\help\n') + g.console_write('\\quit\n') + t.assert(on_stop:get(10)) +end