Skip to content
This repository was archived by the owner on Oct 24, 2025. It is now read-only.

Commit 7f8e9c9

Browse files
committed
Fix memory leaks and improve input_source handling
1 parent d94ca1f commit 7f8e9c9

File tree

5 files changed

+46
-20
lines changed

5 files changed

+46
-20
lines changed

context.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ namespace Sass {
5858
c_options (initializers.c_options()),
5959
c_compiler (initializers.c_compiler()),
6060
source_c_str (initializers.source_c_str()),
61-
sources (vector<const char*>()),
61+
sources (vector<char*>()),
62+
strings (vector<char*>()),
6263
plugin_paths (initializers.plugin_paths()),
6364
include_paths (initializers.include_paths()),
6465
queue (vector<Sass_Queued>()),
@@ -148,12 +149,16 @@ namespace Sass {
148149

149150
Context::~Context()
150151
{
151-
// everything that gets put into sources will be freed by us
152-
for (size_t n = 0; n < import_stack.size(); ++n) sass_delete_import(import_stack[n]);
152+
// make sure we free the source even if not processed!
153+
if (sources.size() == 0 && source_c_str) free(source_c_str);
153154
// sources are allocated by strdup or malloc (overtaken from C code)
154-
for (size_t i = 0; i < sources.size(); ++i) free((void*)sources[i]);
155-
// clear inner structures (vectors)
156-
sources.clear(); import_stack.clear();
155+
for (size_t i = 0; i < sources.size(); ++i) free(sources[i]);
156+
// free all strings we kept alive during compiler execution
157+
for (size_t n = 0; n < strings.size(); ++n) free(strings[n]);
158+
// everything that gets put into sources will be freed by us
159+
for (size_t m = 0; m < import_stack.size(); ++m) sass_delete_import(import_stack[m]);
160+
// clear inner structures (vectors) and input source
161+
sources.clear(); import_stack.clear(); source_c_str = 0;
157162
}
158163

159164
void Context::setup_color_map()
@@ -245,7 +250,7 @@ namespace Sass {
245250
}
246251
}
247252
}
248-
void Context::add_source(string load_path, string abs_path, const char* contents)
253+
void Context::add_source(string load_path, string abs_path, char* contents)
249254
{
250255
sources.push_back(contents);
251256
included_files.push_back(abs_path);
@@ -317,8 +322,10 @@ namespace Sass {
317322
0, 0
318323
);
319324
import_stack.push_back(import);
320-
const char* path = sass_strdup(queue[i].abs_path.c_str());
321-
Parser p(Parser::from_c_str(queue[i].source, *this, ParserState(path, queue[i].source, i)));
325+
// keep a copy of the path around (for parser states)
326+
strings.push_back(sass_strdup(queue[i].abs_path.c_str()));
327+
ParserState pstate(strings.back(), queue[i].source, i);
328+
Parser p(Parser::from_c_str(queue[i].source, *this, pstate));
322329
Block* ast = p.parse();
323330
sass_delete_import(import_stack.back());
324331
import_stack.pop_back();
@@ -369,7 +376,7 @@ namespace Sass {
369376
if(is_indented_syntax_src) {
370377
char * contents = sass2scss(source_c_str, SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
371378
add_source(input_path, input_path, contents);
372-
delete [] source_c_str;
379+
free(source_c_str);
373380
return parse_file();
374381
}
375382
add_source(input_path, input_path, source_c_str);

context.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ namespace Sass {
3737

3838
struct Sass_Options* c_options;
3939
struct Sass_Compiler* c_compiler;
40-
const char* source_c_str;
40+
char* source_c_str;
4141

4242
// c-strs containing Sass file contents
4343
// we will overtake ownership of memory
44-
vector<const char*> sources;
44+
vector<char*> sources;
45+
// strings get freed with context
46+
vector<char*> strings;
4547
// absolute paths to includes
4648
vector<string> included_files;
4749
// relative links to includes
@@ -87,7 +89,7 @@ namespace Sass {
8789
KWD_ARG_SET(Data) {
8890
KWD_ARG(Data, struct Sass_Options*, c_options)
8991
KWD_ARG(Data, struct Sass_Compiler*, c_compiler)
90-
KWD_ARG(Data, const char*, source_c_str)
92+
KWD_ARG(Data, char*, source_c_str)
9193
KWD_ARG(Data, string, entry_point)
9294
KWD_ARG(Data, string, input_path)
9395
KWD_ARG(Data, string, output_path)
@@ -117,7 +119,7 @@ namespace Sass {
117119

118120
Block* parse_file();
119121
Block* parse_string();
120-
void add_source(string, string, const char*);
122+
void add_source(string, string, char*);
121123

122124
string add_file(const string& file);
123125
string add_file(const string& base, const string& file);

sass_context.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ extern "C" {
606606
if (c_ctx == 0) return 0;
607607
Context::Data cpp_opt = Context::Data();
608608
cpp_opt.source_c_str(c_ctx->source_string);
609+
c_ctx->source_string = 0; // passed away
609610
return sass_prepare_context(c_ctx, cpp_opt);
610611
}
611612

@@ -620,6 +621,7 @@ extern "C" {
620621
if (data_ctx->source_string == 0) { throw(runtime_error("Data context has no source string")); }
621622
if (*data_ctx->source_string == 0) { throw(runtime_error("Data context has empty source string")); }
622623
cpp_opt.source_c_str(data_ctx->source_string);
624+
data_ctx->source_string = 0; // passed away
623625
}
624626
catch (...) { return handle_errors(c_ctx) | 1; }
625627
return sass_compile_context(c_ctx, cpp_opt);
@@ -758,6 +760,7 @@ extern "C" {
758760
if (ctx->error_file) free(ctx->error_file);
759761
if (ctx->input_path) free(ctx->input_path);
760762
if (ctx->output_path) free(ctx->output_path);
763+
if (ctx->plugin_path) free(ctx->plugin_path);
761764
if (ctx->include_path) free(ctx->include_path);
762765
if (ctx->source_map_file) free(ctx->source_map_file);
763766
if (ctx->source_map_root) free(ctx->source_map_root);
@@ -781,16 +784,30 @@ extern "C" {
781784

782785
void ADDCALL sass_delete_compiler (struct Sass_Compiler* compiler)
783786
{
784-
if (compiler == 0) return;
787+
if (compiler == 0) {
788+
return;
789+
}
785790
Context* cpp_ctx = compiler->cpp_ctx;
786791
if (cpp_ctx) delete(cpp_ctx);
787792
compiler->cpp_ctx = 0;
788793
free(compiler);
789794
}
790795

791-
// Deallocate all associated memory with contexts
792-
void ADDCALL sass_delete_file_context (struct Sass_File_Context* ctx) { sass_clear_context(ctx); free(ctx); }
793-
void ADDCALL sass_delete_data_context (struct Sass_Data_Context* ctx) { sass_clear_context(ctx); free(ctx); }
796+
// Deallocate all associated memory with file context
797+
void ADDCALL sass_delete_file_context (struct Sass_File_Context* ctx)
798+
{
799+
// clear the context and free it
800+
sass_clear_context(ctx); free(ctx);
801+
}
802+
// Deallocate all associated memory with data context
803+
void ADDCALL sass_delete_data_context (struct Sass_Data_Context* ctx)
804+
{
805+
// clean the source string if it was not passed
806+
// we reset this member once we start parsing
807+
if (ctx->source_string) free(ctx->source_string);
808+
// clear the context and free it
809+
sass_clear_context(ctx); free(ctx);
810+
}
794811

795812
// Getters for sass context from specific implementations
796813
struct Sass_Context* ADDCALL sass_file_context_get_context(struct Sass_File_Context* ctx) { return ctx; }

sass_interface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct sass_options {
4747
struct sass_context {
4848
const char* input_path;
4949
const char* output_path;
50-
const char* source_string;
50+
char* source_string;
5151
char* output_string;
5252
char* source_map_string;
5353
struct sass_options options;

source_map.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace Sass {
1919

2020
const bool include_sources = ctx.source_map_contents;
2121
const vector<string> includes = ctx.include_links;
22-
const vector<const char*> sources = ctx.sources;
22+
const vector<char*> sources = ctx.sources;
2323

2424
JsonNode* json_srcmap = json_mkobject();
2525

0 commit comments

Comments
 (0)