Skip to content

Commit

Permalink
Implement implicit byte checker in C.
Browse files Browse the repository at this point in the history
* Use it in `jl_load_`
* Remove the length parameter from `jl_load`, `jl_load_file_string` and
  `jl_parse_eval_all` to NOT pretend they support non-NUL-terminated strings.
  • Loading branch information
yuyichao committed Jun 27, 2016
1 parent 91488ca commit 5d524ec
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 21 deletions.
4 changes: 2 additions & 2 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,8 @@ end
# remote/parallel load

include_string(txt::String, fname::String) =
ccall(:jl_load_file_string, Any, (Ptr{UInt8},Csize_t,Ptr{UInt8},Csize_t),
txt, sizeof(txt), fname, sizeof(fname))
ccall(:jl_load_file_string, Any, (Ptr{UInt8},Csize_t,Cstring),
txt, sizeof(txt), fname)

include_string(txt::AbstractString, fname::AbstractString="string") =
include_string(String(txt), String(fname))
Expand Down
40 changes: 40 additions & 0 deletions src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,46 @@ JL_DLLEXPORT jl_value_t *(jl_array_data_owner)(jl_array_t *a)
return jl_array_data_owner(a);
}

STATIC_INLINE int jl_has_implicit_byte_owned(jl_array_t *a)
{
assert(a->flags.how != 3);
if (!a->flags.isshared)
return 1;
return a->flags.how == 1;
}

STATIC_INLINE int jl_has_implicit_byte(jl_array_t *a)
{
// * unshared:
// * how: 0-2
// We own and allocated the data.
// It should have the extra byte.
// * shared:
// * how: 0, 2
// The data might come from external source without implicit NUL byte.
// There could be an entra byte for a `reinterpreted` array
// but that should be unlikely for strings.
// * how: 1
// We allocated the data with the extra byte.
// * how: 3
// We should check the owner.
if (a->flags.how == 3) {
a = (jl_array_t*)jl_array_data_owner(a);
return a->elsize == 1 && jl_has_implicit_byte_owned(a);
}
return jl_has_implicit_byte_owned(a);
}

// Create an array with the same content
JL_DLLEXPORT jl_array_t *jl_array_cconvert_cstring(jl_array_t *a)
{
assert(jl_typeof(a) == jl_array_uint8_type);
if (!jl_has_implicit_byte(a))
a = jl_array_copy(a);
((char*)a->data)[a->nrows] = 0;
return a;
}

#ifdef __cplusplus
}
#endif
7 changes: 4 additions & 3 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,14 +641,15 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len,
}

// parse and eval a whole file, possibly reading from a string (`content`)
jl_value_t *jl_parse_eval_all(const char *fname, size_t len,
jl_value_t *jl_parse_eval_all(const char *fname,
const char *content, size_t contentlen)
{
if (in_pure_callback)
jl_error("cannot use include inside a generated function");
jl_ast_context_t *ctx = jl_ast_ctx_enter();
fl_context_t *fl_ctx = &ctx->fl;
value_t f, ast;
size_t len = strlen(fname);
f = cvalue_static_cstrn(fl_ctx, fname, len);
fl_gc_handle(fl_ctx, &f);
if (content != NULL) {
Expand Down Expand Up @@ -723,9 +724,9 @@ jl_value_t *jl_parse_eval_all(const char *fname, size_t len,
}

JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len,
char *filename, size_t namelen)
char *filename)
{
return jl_parse_eval_all(filename, namelen, text, len);
return jl_parse_eval_all(filename, text, len);
}

JL_DLLEXPORT int jl_parse_depwarn(int warn)
Expand Down
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ void _julia_init(JL_IMAGE_SEARCH rel)
jl_all_tls_states[t]->root_task->current_module = jl_current_module;
}

jl_load("boot.jl", sizeof("boot.jl")-1);
jl_load("boot.jl");
jl_get_builtin_hooks();
jl_boot_file_loaded = 1;
jl_init_box_caches();
Expand Down
4 changes: 2 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,7 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len,
int pos0, int greedy);
JL_DLLEXPORT int jl_parse_depwarn(int warn);
JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len,
char *filename, size_t namelen);
char *filename);
JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr);
JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str);

Expand Down Expand Up @@ -1350,7 +1350,7 @@ JL_DLLEXPORT const char *jl_lookup_soname(const char *pfx, size_t n);
// compiler
JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v);
JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex);
JL_DLLEXPORT jl_value_t *jl_load(const char *fname, size_t len);
JL_DLLEXPORT jl_value_t *jl_load(const char *fname);
JL_DLLEXPORT jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
jl_lambda_info_t *lam);
JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m);
Expand Down
4 changes: 3 additions & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ jl_value_t *jl_toplevel_eval_in_warn(jl_module_t *m, jl_value_t *ex,

jl_lambda_info_t *jl_wrap_expr(jl_value_t *expr);
jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e);
jl_value_t *jl_parse_eval_all(const char *fname, size_t len,
jl_value_t *jl_parse_eval_all(const char *fname,
const char *content, size_t contentlen);
jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam);
jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e);
Expand Down Expand Up @@ -662,6 +662,8 @@ STATIC_INLINE void *jl_get_frame_addr(void)
#endif
}

JL_DLLEXPORT jl_array_t *jl_array_cconvert_cstring(jl_array_t *a);

#ifdef __cplusplus
}
#endif
Expand Down
18 changes: 10 additions & 8 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,28 +551,30 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v)
return jl_toplevel_eval_flex(v, 1, 0);
}

JL_DLLEXPORT jl_value_t *jl_load(const char *fname, size_t len)
JL_DLLEXPORT jl_value_t *jl_load(const char *fname)
{
if (NULL != memchr(fname, 0, len))
jl_exceptionf(jl_argumenterror_type, "file name may not contain \\0");
if (jl_current_module->istopmod) {
jl_printf(JL_STDOUT, "%s\r\n", fname);
#ifdef _OS_WINDOWS_
uv_run(uv_default_loop(), (uv_run_mode)1);
#endif
}
char *fpath = (char*)fname;
uv_stat_t stbuf;
if (jl_stat(fpath, (char*)&stbuf) != 0 || (stbuf.st_mode & S_IFMT) != S_IFREG) {
jl_errorf("could not open file %s", fpath);
if (jl_stat(fname, (char*)&stbuf) != 0 || (stbuf.st_mode & S_IFMT) != S_IFREG) {
jl_errorf("could not open file %s", fname);
}
return jl_parse_eval_all(fpath, len, NULL, 0);
return jl_parse_eval_all(fname, NULL, 0);
}

// load from filename given as a String object
JL_DLLEXPORT jl_value_t *jl_load_(jl_value_t *str)
{
return jl_load(jl_string_data(str), jl_string_len(str));
jl_array_t *ary =
jl_array_cconvert_cstring((jl_array_t*)(jl_data_ptr(str)[0]));
JL_GC_PUSH1(&ary);
jl_value_t *res = jl_load((const char*)ary->data);
JL_GC_POP();
return res;
}

// method definition ----------------------------------------------------------
Expand Down
4 changes: 1 addition & 3 deletions test/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ using Base.Test

@test @__LINE__ == 5

@test_throws ArgumentError Core.include("test_sourcepath.jl\0")

include("test_sourcepath.jl")
thefname = "the fname!//\\&\0\1*"
thefname = "the fname!//\\&\1*"
@test include_string("include_string_test() = @__FILE__", thefname)() == Base.source_path()
@test include_string("Base.source_path()", thefname) == Base.source_path()
@test basename(@__FILE__) == "loading.jl"
Expand Down
2 changes: 1 addition & 1 deletion ui/repl.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ static int exec_program(char *program)
JL_EH_POP();
return 1;
}
jl_load(program, strlen(program));
jl_load(program);
}
JL_CATCH {
err = 1;
Expand Down

0 comments on commit 5d524ec

Please sign in to comment.