From 6ac69b1265b9cac40ec04390161dde89c3daa21d Mon Sep 17 00:00:00 2001 From: "Robert G. Jakabosky" Date: Sat, 8 Jan 2011 04:24:25 -0800 Subject: Fixed invalid freeing of Lua strings from git_rawobj_close(). Added support for git_repository_open_no_backend() function. --- CMakeLists.txt | 13 +++++++++++++ config.h.cmake | 17 +++++++++++++++++ database.nobj.lua | 4 ++-- database_backend.nobj.lua | 23 ++++++++++++++++++++--- git2.nobj.lua | 1 + rawobject.nobj.lua | 36 +++++++++++++++++++++++++----------- repository.nobj.lua | 16 ++++++++++++++++ test_backend.lua | 25 +++++++++++++++++++++++-- test_rep.lua | 2 +- 9 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 config.h.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a6f105a..9ae65ae 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,9 +33,22 @@ set(COMMON_CFLAGS "${COMMON_CFLAGS} ${GIT2_CFLAGS}") set(COMMON_LDFLAGS "${COMMON_LDFLAGS} ${GIT2_LDFLAGS}") set(COMMON_LIBS "${COMMON_LIBS};${GIT2_LIBRARIES}") +## check for git_repository_open_no_backend() function. +include(CheckCSourceCompiles) +set(CMAKE_REQUIRED_LIBRARIES "${GIT2_LIBRARIES}") +check_c_source_compiles(" + #include + int main(int argc, char *argv[]) { + return git_repository_open_no_backend(NULL,NULL,NULL,NULL,NULL); + }" HAVE_git_repository_open_no_backend) + ## LuaNativeObjects include(LuaNativeObjects) +## generate config.h +configure_file(${CMAKE_SOURCE_DIR}/config.h.cmake + ${CMAKE_SOURCE_DIR}/build/config.h) + include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${LUA_INCLUDE_DIR}) diff --git a/config.h.cmake b/config.h.cmake new file mode 100644 index 0000000..131df6e --- /dev/null +++ b/config.h.cmake @@ -0,0 +1,17 @@ +/* + * CMake autogenerated config.h file. + * Make changes to config.h.cmake instead of this file. + */ + +/*************************************************************************** + * Copyright (C) 2010 by Robert G. Jakabosky * + * * + ***************************************************************************/ + +#ifndef __LUA_GIT2_CONFIG_H__ +#define __LUA_GIT2_CONFIG_H__ + +/* libgit2 feature support */ +#cmakedefine HAVE_git_repository_open_no_backend + +#endif /* __LUA_GIT2_CONFIG_H__ */ diff --git a/database.nobj.lua b/database.nobj.lua index a5ad94b..0f65269 100644 --- a/database.nobj.lua +++ b/database.nobj.lua @@ -57,7 +57,7 @@ object "Database" { ${err} = git_odb_read(&(git), ${this}, &(${id})); if(${err} == GIT_SUCCESS) { /* convert git_rawobj to RawObject */ - RawObject_from_git_rawobj(L, &raw, &git); + RawObject_from_git_rawobj(L, &raw, &git, true); ${obj} = &(raw); } ]], @@ -72,7 +72,7 @@ object "Database" { ${err} = git_odb_read_header(&(git), ${this}, &(${id})); if(${err} == GIT_SUCCESS) { /* convert git_rawobj to RawObject */ - RawObject_from_git_rawobj(L, &raw, &git); + RawObject_from_git_rawobj(L, &raw, &git, true); ${obj} = &(raw); } ]], diff --git a/database_backend.nobj.lua b/database_backend.nobj.lua index 61b37ab..4a8d139 100644 --- a/database_backend.nobj.lua +++ b/database_backend.nobj.lua @@ -64,7 +64,21 @@ static int database_backend_read_cb(git_rawobj *obj, git_odb_backend *backend, c err = lua_tointeger(L, -1); if(err == 0) { RawObject *raw_obj = obj_type_RawObject_check(L,-2); - *obj = raw_obj->git; + /* copy header fields. */ + obj->len = raw_obj->git.len; + obj->type = raw_obj->git.type; + /* we must malloc & copy the RawObject's data. */ + if(raw_obj->git.data) { + obj->data = malloc(obj->len); + if(obj->data == NULL) { + /* failed to allocate buffer. */ + return GIT_ENOMEM; + } + /* copy data. */ + memcpy(obj->data, raw_obj->git.data, obj->len); + } else { + obj->data = NULL; + } } return err; @@ -85,7 +99,10 @@ static int database_backend_read_header_cb(git_rawobj *obj, git_odb_backend *bac err = lua_tointeger(L, -1); if(err == 0) { RawObject *raw_obj = obj_type_RawObject_check(L,-2); - *obj = raw_obj->git; + /* copy only header fields. */ + obj->data = NULL; + obj->len = raw_obj->git.len; + obj->type = raw_obj->git.type; } return err; @@ -102,7 +119,7 @@ static int database_backend_write_cb(git_oid *oid, git_odb_backend *backend, git lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->write); /* convert git_rawobj to RawObject */ - RawObject_from_git_rawobj(L, &raw, obj); + RawObject_from_git_rawobj(L, &raw, obj, false); /* push RawObject onto stack. */ obj_type_RawObject_push(L, &raw, 0); diff --git a/git2.nobj.lua b/git2.nobj.lua index 47e703a..6aef684 100644 --- a/git2.nobj.lua +++ b/git2.nobj.lua @@ -5,6 +5,7 @@ use_globals = false, hide_meta_info = false, --true, include "git2.h", +include "config.h", package "GIT" { const "SUCCESS" { 0 }, diff --git a/rawobject.nobj.lua b/rawobject.nobj.lua index 6f14156..ec087e2 100644 --- a/rawobject.nobj.lua +++ b/rawobject.nobj.lua @@ -40,14 +40,18 @@ static void RawObject_set_data_and_ref(lua_State *L, RawObject *raw, const char } } -static void RawObject_from_git_rawobj(lua_State *L, RawObject *raw, const git_rawobj *git) { - /* push raw object's data onto stack. */ - lua_pushlstring(L, git->data, git->len); - /* get Lua's pointer to the string. */ - raw->git.data = (void *)lua_tolstring(L, -1, &(raw->git.len)); - raw->git.type = git->type; - /* get reference to string. */ - raw->ref = luaL_ref(L, LUA_REGISTRYINDEX); +static void RawObject_from_git_rawobj(lua_State *L, RawObject *raw, git_rawobj *git, int cleanup) { + /* push raw object's data onto stack. */ + lua_pushlstring(L, git->data, git->len); + /* get Lua's pointer to the string. */ + raw->git.data = (void *)lua_tolstring(L, -1, &(raw->git.len)); + raw->git.type = git->type; + /* get reference to string. */ + raw->ref = luaL_ref(L, LUA_REGISTRYINDEX); + /* clean-up git_rawobj. */ + if(cleanup && git->data != NULL) { + git_rawobj_close(git); + } } ]] @@ -55,7 +59,19 @@ static void RawObject_from_git_rawobj(lua_State *L, RawObject *raw, const git_ra object "RawObject" { userdata_type = 'embed', default = 'NULL', - constructor { + constructor "header" { + var_in{"const char *", "type"}, + var_in{"size_t", "len"}, + c_source [[ + RawObject raw; /* temp. storage, this gets copied. */ + ${this} = &(raw); + raw.git.data = NULL; + raw.git.len = ${len}; + raw.git.type = git_object_string2type(${type}); + raw.ref = LUA_REFNIL; +]], + }, + constructor "new" { var_in{"const char *", "type"}, var_in{"const char *", "data"}, c_source [[ @@ -71,8 +87,6 @@ object "RawObject" { luaL_unref(L, LUA_REGISTRYINDEX, ${this}->ref); ${this}->ref = LUA_REFNIL; ${this}->git.data = NULL; - ${this}->git.len = 0; - RawObject_set_data_and_ref(L, ${this}, NULL, 0, 0); ]], }, method "data" { diff --git a/repository.nobj.lua b/repository.nobj.lua index 5b281c7..dbdef00 100644 --- a/repository.nobj.lua +++ b/repository.nobj.lua @@ -20,6 +20,7 @@ c_source [[ typedef git_repository Repository; + ]] object "Repository" { @@ -38,6 +39,21 @@ object "Repository" { var_out{"GitError", "err"}, c_source [[ ${err} = git_repository_open2(&(${this}), ${dir}, ${object_directory}, ${index_file}, ${work_tree}); +]], + }, + constructor "open_no_backend" { + var_in{"const char *", "dir"}, + var_in{"const char *", "object_directory"}, + var_in{"const char *", "index_file"}, + var_in{"const char *", "work_tree"}, + var_out{"GitError", "err"}, + c_source [[ +#ifdef HAVE_git_repository_open_no_backend + ${err} = git_repository_open_no_backend(&(${this}), ${dir}, ${object_directory}, ${index_file}, ${work_tree}); +#else + luaL_error(L, "Your version of LibGit2 doesn't have 'git_repository_open_no_backend'"); +#endif + ]], }, constructor "init" { diff --git a/test_backend.lua b/test_backend.lua index 9708adf..c65eef6 100644 --- a/test_backend.lua +++ b/test_backend.lua @@ -1,7 +1,7 @@ #!/usr/bin/env lua local build_dir = arg[1] -local git_path = arg[2] or "./test_rep/.git" +local git_path = arg[2] or "./test_rep/.git/" -- Make it easier to test if ( build_dir ) then package.cpath = build_dir .. "?.so;" .. package.cpath @@ -87,7 +87,7 @@ local backend = git2.DatabaseBackend(cbs, 1) print('add backend:', assert(db:add_backend(backend))) print('create test blob:') -local raw_obj = git2.RawObject('blob',"any ol content will do") +local raw_obj = git2.RawObject.new('blob',"any ol content will do") print("test writing RawObject to database:") local oid, err = db:write(raw_obj) @@ -109,6 +109,27 @@ for _,obj in ipairs(object_ids) do print() end +local status, rep = pcall(git2.Repository.open_no_backend, + git_path, git_path .. 'objects', git_path .. 'index', git_path .. '../') + +print(status, rep) + +print() +print("try reading objects from repository:") +local object_ids = { + {'tree', "31f3d5703ce27f0b63c3eb0d829abdc95b51deae"}, + {'commit', "d5a93c463d4cca0068750eb6af7b4b54eea8599b"}, + {'blob', "f534deb63f967cddd4bd440d05d3f6f075e55fca"}, + {'blob', "275a4019807c7bb7bc80c0ca8903bf84345e1bdf"}, +} +for _,obj in ipairs(object_ids) do + local oid = git2.OID.str(obj[2]) + local obj, err = rep:lookup(oid, obj[1]) + print('read', obj, err) + dump_rawobj(obj) + print() +end + db = nil backend = nil diff --git a/test_rep.lua b/test_rep.lua index f175b1d..f7c289c 100644 --- a/test_rep.lua +++ b/test_rep.lua @@ -24,7 +24,7 @@ print(dbg_dump(oid)) print('convert OID value to string = <' .. tostring(oid) .. '>') print('test writing to the object database:') -local raw_obj = git2.RawObject('blob',"any ol content will do") +local raw_obj = git2.RawObject.new('blob',"any ol content will do") print() print("dump RawObject interface") print(dbg_dump(raw_obj)) -- cgit v1.2.1