From 69b84e94ead99fe7f0017a1dc4ac263f6a07b09f Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 14 Jan 2015 00:50:02 -0500 Subject: [PATCH] fix various code issues: some formatting cleanup, some missing gc roots, some potential alignment issues, and a strcpy buffer overflow at startup --- src/alloc.c | 35 ++++++--- src/builtins.c | 17 ++-- src/dump.c | 2 +- src/flisp/basename.c | 181 ------------------------------------------- src/init.c | 3 +- src/intrinsics.cpp | 9 ++- src/jl_uv.c | 2 +- src/jltypes.c | 9 ++- src/support/ios.c | 5 +- ui/repl.c | 5 +- 10 files changed, 52 insertions(+), 216 deletions(-) delete mode 100644 src/flisp/basename.c diff --git a/src/alloc.c b/src/alloc.c index 72abc7fa378be..5e08aa05a0f1a 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -186,11 +186,17 @@ DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i) JL_TYPECHK(pointerref, pointer, p); JL_TYPECHK(pointerref, long, i); jl_value_t *ety = jl_tparam0(jl_typeof(p)); - if (!jl_is_datatype(ety)) - jl_error("pointerref: invalid pointer"); - size_t nb = jl_datatype_size(ety); - char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb; - return jl_new_bits(ety, pp); + if (ety == (jl_value_t*)jl_any_type) { + jl_value_t **pp = (jl_value_t**)(jl_unbox_long(p) + (jl_unbox_long(i)-1)*sizeof(void*)); + return *pp; + } + else { + if (!jl_is_datatype(ety)) + jl_error("pointerref: invalid pointer"); + size_t nb = LLT_ALIGN(jl_datatype_size(ety), ((jl_datatype_t*)ety)->alignment); + char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb; + return jl_new_bits(ety, pp); + } } void jl_assign_bits(void *dest, jl_value_t *bits) @@ -213,13 +219,18 @@ DLLEXPORT void jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *i) JL_TYPECHK(pointerset, pointer, p); JL_TYPECHK(pointerset, long, i); jl_value_t *ety = jl_tparam0(jl_typeof(p)); - if (!jl_is_datatype(ety)) - jl_error("pointerset: invalid pointer"); - size_t nb = jl_datatype_size(ety); - char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb; - if (jl_typeof(x) != ety) - jl_error("pointerset: type mismatch in assign"); - jl_assign_bits(pp, x); + if (ety == (jl_value_t*)jl_any_type) { + jl_value_t **pp = (jl_value_t**)(jl_unbox_long(p) + (jl_unbox_long(i)-1)*sizeof(void*)); + *pp = x; + } else { + if (!jl_is_datatype(ety)) + jl_error("pointerset: invalid pointer"); + size_t nb = LLT_ALIGN(jl_datatype_size(ety), ((jl_datatype_t*)ety)->alignment); + char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb; + if (jl_typeof(x) != ety) + jl_error("pointerset: type mismatch in assign"); + jl_assign_bits(pp, x); + } } int jl_field_index(jl_datatype_t *t, jl_sym_t *fld, int err) diff --git a/src/builtins.c b/src/builtins.c index b9286d883655f..028ea2be552b0 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -405,10 +405,6 @@ JL_CALLABLE(jl_f_apply) return jl_apply(f, &jl_tupleref(args[1],0), jl_tuple_len(args[1])); } } - jl_value_t *argarr = NULL; - JL_GC_PUSH1(&argarr); - jl_value_t *result; - jl_value_t **newargs; size_t n=0, i, j; for(i=1; i < nargs; i++) { if (jl_is_tuple(args[i])) { @@ -426,20 +422,23 @@ JL_CALLABLE(jl_f_apply) JL_TYPECHK(apply, tuple, args[i]); } } - argarr = jl_apply(jl_append_any_func, &args[1], nargs-1); + jl_value_t *argarr = jl_apply(jl_append_any_func, &args[1], nargs-1); assert(jl_typeis(argarr, jl_array_any_type)); - result = jl_apply(f, jl_cell_data(argarr), jl_array_len(argarr)); + JL_GC_PUSH1(&argarr); + jl_value_t *result = jl_apply(f, jl_cell_data(argarr), jl_array_len(argarr)); JL_GC_POP(); return result; } } + jl_value_t **newargs; if (n > jl_page_size/sizeof(jl_value_t*)) { // put arguments on the heap if there are too many - argarr = (jl_value_t*)jl_alloc_cell_1d(n); + jl_value_t *argarr = (jl_value_t*)jl_alloc_cell_1d(n); + JL_GC_PUSH1(&argarr); newargs = jl_cell_data(argarr); } else { - newargs = (jl_value_t**)alloca(n * sizeof(jl_value_t*)); + JL_GC_PUSHARGS(newargs, n); } n = 0; for(i=1; i < nargs; i++) { @@ -455,7 +454,7 @@ JL_CALLABLE(jl_f_apply) newargs[n++] = jl_cellref(args[i], j); } } - result = jl_apply(f, newargs, n); + jl_value_t *result = jl_apply(f, newargs, n); JL_GC_POP(); return result; } diff --git a/src/dump.c b/src/dump.c index ae220b78d9663..e291d171b5bdc 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1379,7 +1379,7 @@ void jl_restore_system_image(const char *fname) if (jl_is_debugbuild()) build_mode = 1; #endif if (!build_mode) { - char *fname_shlib = (char*)alloca(strlen(fname)); + char *fname_shlib = (char*)alloca(strlen(fname)+1); strcpy(fname_shlib, fname); char *fname_shlib_dot = strrchr(fname_shlib, '.'); if (fname_shlib_dot != NULL) *fname_shlib_dot = 0; diff --git a/src/flisp/basename.c b/src/flisp/basename.c deleted file mode 100644 index e1a256249e523..0000000000000 --- a/src/flisp/basename.c +++ /dev/null @@ -1,181 +0,0 @@ -/** - * @file basename.c - * Copyright 2012, 2013 MinGW.org project - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* - * Provides an implementation of the "basename" function, conforming - * to SUSv3, with extensions to accommodate Win32 drive designators, - * and suitable for use on native Microsoft(R) Win32 platforms. - */ - -#include -#include -#include -#include -#include -#include "dtypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -DLLEXPORT char *basename( char *path ) -{ - size_t len; - static char *retfail = NULL; - - /* to handle path names for files in multibyte character locales, - * we need to set up LC_CTYPE to match the host file system locale - */ - - char *locale = setlocale( LC_CTYPE, NULL ); - if( locale != NULL ) locale = strdup( locale ); - setlocale( LC_CTYPE, "" ); - - if( path && *path ) - { - /* allocate sufficient local storage space, - * in which to create a wide character reference copy of path - */ - - wchar_t *refcopy = (wchar_t*)alloca((1 + (len = mbstowcs(NULL, path, 0)))*sizeof(wchar_t)); - - /* create the wide character reference copy of path, - * and step over the drive designator, if present ... - */ - - wchar_t *refpath = refcopy; - if( ((len = mbstowcs( refpath, path, len )) > 1) && (refpath[1] == L':') ) - { - /* FIXME: maybe should confirm *refpath is a valid drive designator */ - - refpath += 2; - } - - /* ensure that our wide character reference path is NUL terminated */ - - refcopy[ len ] = L'\0'; - - /* check again, just to ensure we still have a non-empty path name ... */ - - if( *refpath ) - { - /* and, when we do, process it in the wide character domain ... - * scanning from left to right, to the char after the final dir separator - */ - - wchar_t *refname; - for( refname = refpath ; *refpath ; ++refpath ) - { - if( (*refpath == L'/') || (*refpath == L'\\') ) - { - /* we found a dir separator ... - * step over it, and any others which immediately follow it - */ - - while( (*refpath == L'/') || (*refpath == L'\\') ) - ++refpath; - - /* if we didn't reach the end of the path string ... */ - - if( *refpath ) - - /* then we have a new candidate for the base name */ - - refname = refpath; - - /* otherwise ... - * strip off any trailing dir separators which we found - */ - - else while( (refpath > refname) - && ((*--refpath == L'/') || (*refpath == L'\\')) ) - *refpath = L'\0'; - } - } - - /* in the wide character domain ... - * refname now points at the resolved base name ... - */ - - if( *refname ) - { - /* if it's not empty, - * then we transform the full normalised path back into - * the multibyte character domain, and skip over the dirname, - * to return the resolved basename. - */ - - if( (len = wcstombs( path, refcopy, len )) != (size_t)(-1) ) - path[ len ] = '\0'; - *refname = L'\0'; - if( (len = wcstombs( NULL, refcopy, 0 )) != (size_t)(-1) ) - path += len; - } - - else - { - /* the basename is empty, so return the default value of "/", - * transforming from wide char to multibyte char domain, and - * returning it in our own buffer. - */ - - retfail = (char*)realloc( retfail, len = 1 + wcstombs( NULL, L"/", 0 )); - wcstombs( path = retfail, L"/", len ); - } - - /* restore the caller's locale, clean up, and return the result */ - - setlocale( LC_CTYPE, locale ); - free( locale ); - return( path ); - } - - /* or we had an empty residual path name, after the drive designator, - * in which case we simply fall through ... - */ - } - - /* and, if we get to here ... - * the path name is either NULL, or it decomposes to an empty string; - * in either case, we return the default value of "." in our own buffer, - * reloading it with the correct value, transformed from the wide char - * to the multibyte char domain, just in case the caller trashed it - * after a previous call. - */ - - retfail = (char*)realloc( retfail, len = 1 + wcstombs( NULL, L".", 0 )); - wcstombs( retfail, L".", len ); - - /* restore the caller's locale, clean up, and return the result */ - - setlocale( LC_CTYPE, locale ); - free( locale ); - return( retfail ); -} - -#ifdef __cplusplus -} -#endif - -/* $RCSfile: basename.c,v $$Revision: 1.2 $: end of file */ diff --git a/src/init.c b/src/init.c index d0daa524cac6f..3bd3f39391221 100644 --- a/src/init.c +++ b/src/init.c @@ -806,7 +806,7 @@ int isabspath(const char *in) } } #else - if (jl_compileropts.image_file[0] == '/') return 1; // absolute path + if (in[0] == '/') return 1; // absolute path #endif return 0; // relative path } @@ -834,6 +834,7 @@ static char *abspath(const char *in) path[path_size-1] = PATHSEPSTRING[0]; memcpy(path+path_size, in, len+1); out = strdup(path); + free(path); } } #else diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 6ba00608a84b4..37c7f96cf4619 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -620,14 +620,15 @@ static Value *emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx) return NULL; } assert(jl_is_datatype(ety)); - uint64_t size = ((jl_datatype_t*)ety)->size; + uint64_t size = jl_datatype_size(ety); Value *strct = builder.CreateCall(prepare_call(jlallocobj_func), ConstantInt::get(T_size, sizeof(void*)+size)); builder.CreateStore(literal_pointer_val((jl_value_t*)ety), emit_nthptr_addr(strct, (size_t)0)); - im1 = builder.CreateMul(im1, ConstantInt::get(T_size, size)); + im1 = builder.CreateMul(im1, ConstantInt::get(T_size, + LLT_ALIGN(size, ((jl_datatype_t*)ety)->alignment))); thePtr = builder.CreateGEP(builder.CreateBitCast(thePtr, T_pint8), im1); builder.CreateMemCpy(builder.CreateBitCast(emit_nthptr_addr(strct, (size_t)1), T_pint8), thePtr, size, 1); @@ -682,8 +683,10 @@ static Value *emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_co assert(val->getType() == jl_pvalue_llvmt); //Boxed assert(jl_is_datatype(ety)); uint64_t size = ((jl_datatype_t*)ety)->size; + im1 = builder.CreateMul(im1, ConstantInt::get(T_size, + LLT_ALIGN(size, ((jl_datatype_t*)ety)->alignment))); builder.CreateMemCpy(builder.CreateGEP(builder.CreateBitCast(thePtr, T_pint8), im1), - builder.CreateBitCast(emit_nthptr_addr(val, (size_t)1),T_pint8), size, 1); + builder.CreateBitCast(emit_nthptr_addr(val, (size_t)1), T_pint8), size, 1); } else { if (val == NULL) { diff --git a/src/jl_uv.c b/src/jl_uv.c index 0e2e9bfe944c2..38c8315212dbf 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -531,7 +531,7 @@ DLLEXPORT void jl_uv_writecb_task(uv_write_t *req, int status) DLLEXPORT int jl_write_copy(uv_stream_t *stream, const char *str, size_t n, uv_write_t *uvw, void *writecb) { JL_SIGATOMIC_BEGIN(); - char *data = (char*)(uvw+1); + char *data = (char*)uvw+sizeof(*uvw); memcpy(data,str,n); uv_buf_t buf[1]; buf[0].base = data; diff --git a/src/jltypes.c b/src/jltypes.c index f2825bad2eab8..6ff3544676058 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2684,8 +2684,10 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, if (jl_is_uniontype(child)) { jl_tuple_t *t = ((jl_uniontype_t*)child)->types; if (morespecific) { - cenv_t tenv; - tenv.data = (jl_value_t**)alloca(MAX_CENV_SIZE*sizeof(void*)); + jl_value_t **rts; + JL_GC_PUSHARGS(rts, MAX_CENV_SIZE); + cenv_t tenv; tenv.data = rts; + memset(tenv.data, 0, MAX_CENV_SIZE*sizeof(void*)); for(i=0; i < jl_tuple_len(t); i++) { int n = env->n; tmp = type_match_(jl_tupleref(t,i), parent, env, 1, invariant); @@ -2703,9 +2705,11 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, type_match_(jl_tupleref(t,j), parent, env, 1, invariant) == jl_false) { env->n = n; + JL_GC_POP(); return jl_false; } } + JL_GC_POP(); return jl_true; } } @@ -2713,6 +2717,7 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, env->n = n; } } + JL_GC_POP(); return jl_false; } else { diff --git a/src/support/ios.c b/src/support/ios.c index d8bd66c7ede4f..bf6d83ba941e0 100644 --- a/src/support/ios.c +++ b/src/support/ios.c @@ -847,11 +847,10 @@ ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int tru if (create) flags |= O_CREAT; if (trunc) flags |= O_TRUNC; #if defined(_OS_WINDOWS_) - size_t len = strlen(fname)+1; - size_t wlen = MultiByteToWideChar(CP_UTF8, 0, fname, len, NULL, 0); + size_t wlen = MultiByteToWideChar(CP_UTF8, 0, fname, -1, NULL, 0); if (!wlen) goto open_file_err; wchar_t *fname_w = (wchar_t*)alloca(wlen*sizeof(wchar_t)); - if (!MultiByteToWideChar(CP_UTF8, 0, fname, len, fname_w, wlen)) goto open_file_err; + if (!MultiByteToWideChar(CP_UTF8, 0, fname, -1, fname_w, wlen)) goto open_file_err; fd = _wopen(fname_w, flags | O_BINARY, _S_IREAD | _S_IWRITE); #else fd = open(fname, flags, S_IRUSR | S_IWUSR /* 0600 */ | S_IRGRP | S_IROTH /* 0644 */); diff --git a/ui/repl.c b/ui/repl.c index aa72e7a6ae84e..46ed15bc3d943 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -372,11 +372,10 @@ int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) int i; for (i=0; i