Backported fixes

This commit is contained in:
Arnaud Diederen
2019-12-09 10:10:26 +01:00
parent c436c06731
commit f7e52a0c30
14 changed files with 154 additions and 81 deletions
+18 -9
View File
@@ -151,10 +151,10 @@ static bool find_libpython_dt_needed_info(
//-------------------------------------------------------------------------
static bool patch_dt_needed(
const char *path,
const qstring &replacement,
const qstring &_replacement,
qstring *errbuf)
{
out_verb("Setting relevant DT_NEEDED of \"%s\" to \"%s\"\n", path, replacement.c_str());
out_verb("Setting relevant DT_NEEDED of \"%s\" to \"%s\"\n", path, _replacement.c_str());
out_ident_inc_t iinc;
linput_t *linput = open_linput(path, /*remote=*/ false);
if ( linput == nullptr )
@@ -214,13 +214,24 @@ static bool patch_dt_needed(
room = qltell(reader.get_linput()) - dt_needed_off - 1;
}
const size_t nbytes = replacement.length();
bytevec_t replacement;
replacement.append(_replacement.c_str(), _replacement.length() + 1);
size_t nbytes = replacement.size();
out_verb("We have room for %" FMT_Z " bytes, and need to write %" FMT_Z "\n",
room, nbytes);
// and patch
if ( room >= nbytes )
{
if ( room > nbytes )
{
out_verb("Expanding replacement with %" FMT_Z " '\\0' bytes, to "
"override possible previous soname that could derail "
"later computation of available room.\n", room - nbytes);
replacement.resize(room, 0);
nbytes = replacement.size();
}
FILE *fp = openM(path);
if ( fp != nullptr )
{
@@ -230,7 +241,7 @@ static bool patch_dt_needed(
if ( !args.dry_run )
{
// we want to write the zero as well!
if ( qfwrite(fp, replacement.c_str(), nbytes+1) == nbytes+1 )
if ( qfwrite(fp, replacement.begin(), nbytes) == nbytes )
{
out_verb("File \"%s\" successfully patched\n", path);
}
@@ -243,7 +254,7 @@ static bool patch_dt_needed(
else
{
out("Would write %" FMT_Z " bytes (\"%s\") to file\n",
nbytes, replacement.c_str());
nbytes, replacement.begin());
}
}
else
@@ -263,7 +274,7 @@ static bool patch_dt_needed(
errbuf->sprnt("Replacement \"%s\" has a length of %" FMT_Z
" bytes, but there is only room for %" FMT_Z ""
" bytes in the file. Cannot proceed.\n",
replacement.c_str(), nbytes, room);
replacement.begin(), nbytes, room);
return false;
}
return true;
@@ -460,9 +471,7 @@ static bool split_debug_expand_libpython3_dtneeded_room(
out_verb("\"%s\" command successful. Restoring the "
"original DT_NEEDED of \"%s\"\n",
cmdline.c_str(), dt_needed);
qstring padded_dt_needed(dt_needed);
padded_dt_needed.resize(SLOT_SIZE, '\0');
if ( !patch_dt_needed(path, padded_dt_needed, errbuf) )
if ( !patch_dt_needed(path, dt_needed, errbuf) )
return false;
}
else
+8 -3
View File
@@ -167,14 +167,19 @@ static bool has_appx_path(qstrvec_t paths)
if ( appx_path.empty() )
{
HKEY hkey;
bool ok = false;
if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Appx", 0, KEY_READ, &hkey) == ERROR_SUCCESS )
{
if ( !read_string(&appx_path, hkey, L"PackageRoot") )
appx_path = "<none>";
ok = read_string(&appx_path, hkey, L"PackageRoot");
RegCloseKey(hkey);
}
if ( !ok )
{
// no Appx support, set to dummy value which doesn't occur in paths
appx_path = "<none>";
}
}
for ( auto path : paths )
for ( const qstring &path : paths )
if ( path.find(appx_path) != qstring::npos )
return true;
+32 -7
View File
@@ -254,6 +254,9 @@ void ida_export idapython_hide_wait_box()
#define LEXEC(...)
#endif
#define AVERAGE_STEPS_COUNT 10
#define MAX_STEPS_COUNT ((AVERAGE_STEPS_COUNT * 2) + 1)
//-------------------------------------------------------------------------
void execution_t::reset_steps()
{
@@ -268,7 +271,7 @@ void execution_t::reset_steps()
// If we never hit the 'trace' callback while in the 'while True' loop
// but always when performing the call to the processor module's 'out/outop'
// then the loop will never stop. That was happening on windows (optimized.)
steps_before_action = 1 + rand() % 20;
steps_before_action = 1 + rand() % (AVERAGE_STEPS_COUNT*2);
}
//-------------------------------------------------------------------------
@@ -300,6 +303,7 @@ void execution_t::stop_tracking()
void execution_t::sync_to_present_time()
{
time_t now = time(NULL);
LEXEC("execution_t (%p)::sync_to_present_time() now=%d\n", this, int(now));
for ( size_t i = 0, n = entries.size(); i < n; ++i )
entries[i].etime = now;
maybe_hide_wait_box();
@@ -342,16 +346,38 @@ void execution_t::reset_current_start_time()
//------------------------------------------------------------------------
int execution_t::on_trace(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)
{
LEXEC("on_trace() (steps=%d, nentries=%d)\n",
#ifdef TESTABLE_BUILD
// ensure there was no decrement overflow
QASSERT(0, execution.steps_before_action <= MAX_STEPS_COUNT);
#endif
LEXEC("on_trace() (steps_before_action=%u, entries.size()=%d, timeout=%d)\n",
int(execution.steps_before_action),
int(execution.entries.size()));
// we don't want to query for time at every trace event
if ( execution.steps_before_action-- > 0 )
int(execution.entries.size()),
execution.timeout);
if ( execution.timeout < 0 )
{
LEXEC("on_trace()::no timeout currently set (%d).\n", execution.timeout);
return 0;
}
// we don't want to query for time at every trace event
if ( execution.steps_before_action > 0 )
{
--execution.steps_before_action;
return 0;
}
if ( get_active_modal_widget() != NULL )
{
LEXEC("on_trace()::a modal widget is active. Not showing our 'interrupt dialog'.\n");
// in addition, we want to sync the "start time" to now, so that
// the timeout will be relative to that (otherwise, calling
// ask_file() might end up showing the waitdialog for a fraction
// of a second after `_ida_kernwin.ask_file()` returns, but before
// the `ida_kernwin.ask_file()` one does.)
execution.sync_to_present_time();
return 0;
}
@@ -377,8 +403,7 @@ int execution_t::on_trace(PyObject *obj, PyFrameObject *frame, int what, PyObjec
{
if ( PyErr_Occurred() == NULL )
{
LEXEC("on_trace()::INTERRUPTING (setting 'User interrupted' exception) at line %d\n",
PyFrame_GetLineNumber(frame));
LEXEC("on_trace()::INTERRUPTING (setting 'User interrupted' exception)\n");
PyErr_SetString(PyExc_KeyboardInterrupt, "User interrupted");
}
return -1;
Binary file not shown.
+6 -18
View File
@@ -444,8 +444,7 @@ def save_database(idbname, flags=0):
if len(idbname) == 0:
idbname = get_idb_path()
mask = ida_loader.DBFL_KILL | ida_loader.DBFL_COMP | ida_loader.DBFL_BAK
res = ida_loader.save_database_ex(idbname, flags & mask)
return res
return ida_loader.save_database(idbname, flags & mask)
DBFL_BAK = ida_loader.DBFL_BAK # for compatiblity with older versions, eventually delete this
@@ -509,14 +508,14 @@ def delete_all_segments():
ida_name.del_global_name(ea)
func = ida_funcs.get_func(ea)
if func:
ida_funcs.del_func_cmt(func, False)
ida_funcs.del_func_cmt(func, True)
ida_funcs.set_func_cmt(func, "", False)
ida_funcs.set_func_cmt(func, "", True)
ida_funcs.del_func(ea)
ida_bytes.del_hidden_range(ea)
seg = ida_segment.getseg(ea)
if seg:
ida_segment.del_segment_cmt(seg, False)
ida_segment.del_segment_cmt(seg, True)
ida_segment.set_segment_cmt(seg, "", False)
ida_segment.set_segment_cmt(seg, "", True)
ida_segment.del_segm(ea, ida_segment.SEGMOD_KEEP | ida_segment.SEGMOD_SILENT)
ea = ida_bytes.next_head(ea, ida_ida.cvar.inf.max_ea)
@@ -1007,18 +1006,7 @@ def op_offset_high16(ea, n, target):
def MakeVar(ea):
"""
Mark the location as "variable"
@param ea: address to mark
@return: None
@note: All that IDA does is to mark the location as "variable".
Nothing else, no additional analysis is performed.
This function may disappear in the future.
"""
ida_bytes.doVar(ea, 1)
pass
# Every anterior/posterior line has its number.
# Anterior lines have numbers from E_PREV
+18 -12
View File
@@ -358,6 +358,12 @@ static int get_pyidc_cvt_type(PyObject *py_var)
return int(IDAPyIntOrLong_AsLong(attr.o));
}
//-------------------------------------------------------------------------
static inline bool is_pyidc_cvt_type_int64(PyObject *py_var)
{
return get_pyidc_cvt_type(py_var) == PY_ICID_INT64;
}
//-------------------------------------------------------------------------
// Utility function to convert a python object to an IDC object
// and sets a python exception on failure.
@@ -736,15 +742,9 @@ int ida_export pyvar_to_idcvar(
}
//-------------------------------------------------------------------------
inline PyObject *cvt_to_pylong(int32 v)
{
return PyLong_FromLong(v);
}
inline PyObject *cvt_to_pylong(int64 v)
{
return PyLong_FromLongLong(v);
}
// helpers to use with idc_value_t::num (which can be 32-, or 64-bit.)
inline PyObject *cvt_to_pylong(int32 v) { return PyLong_FromLong(v); }
inline PyObject *cvt_to_pylong(int64 v) { return PyLong_FromLongLong(v); }
//-------------------------------------------------------------------------
// Converts an IDC variable to a Python variable
@@ -786,8 +786,7 @@ int ida_export idcvar_to_pyvar(
if ( *py_var != NULL )
{
// Recycling an int64 object?
int t = get_pyidc_cvt_type(py_var->o);
if ( t != PY_ICID_INT64 )
if ( !is_pyidc_cvt_type_int64(py_var->o) )
return CIP_IMMUTABLE; // Cannot recycle immutable object
// Update the attribute
PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64));
@@ -818,7 +817,14 @@ int ida_export idcvar_to_pyvar(
case VT_LONG:
// Cannot recycle immutable objects
if ( *py_var != NULL )
return CIP_IMMUTABLE;
{
// Recycling an int64 object?
if ( !is_pyidc_cvt_type_int64(py_var->o) )
return CIP_IMMUTABLE;
// Update the attribute
PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, cvt_to_pylong(idc_var.num));
return CIP_OK;
}
*py_var = newref_t(cvt_to_pylong(idc_var.num));
break;
case VT_FLOAT:
+3 -1
View File
@@ -842,7 +842,9 @@ protected:
{
// identifier
{
ref_t py_id = newref_t(PyObject_GetAttrString(self, "id"));
ref_t py_id;
if ( PyObject_HasAttrString(self, "id") )
py_id = newref_t(PyObject_GetAttrString(self, "id"));
if ( py_id == NULL || !IDAPyStr_Check(py_id.o) )
py_id = newref_t(PyObject_Repr(self));
if ( py_id != NULL && IDAPyStr_Check(py_id.o) )
+9
View File
@@ -126,6 +126,15 @@ class quick_widget_commands_t:
cmd.icon)
attach_dynamic_action_to_popup(widget, popup, desc)
class disabled_script_timeout_t(object):
def __enter__(self):
import _ida_idaapi
self.was_timeout = _ida_idaapi.set_script_timeout(0)
def __exit__(self, type, value, tb):
import _ida_idaapi
_ida_idaapi.set_script_timeout(self.was_timeout)
# ----------------------------------------------------------------------
# bw-compat/deprecated. You shouldn't rely on this in new code
from ida_pro import str2user
+1 -4
View File
@@ -1384,15 +1384,12 @@ except:
def __call_form_callable(call, *args):
assert(len(args))
old = _ida_idaapi.set_script_timeout(0)
try:
with disabled_script_timeout_t():
if sys.version_info.major >= 3 and isinstance(args[0], str):
largs = list(args)
largs[0] = largs[0].encode("UTF-8")
args = tuple(largs)
r = call(*args)
finally:
_ida_idaapi.set_script_timeout(old)
return r
def ask_form(*args):
+2 -3
View File
@@ -205,9 +205,8 @@ class Choose(object):
self.flags |= Choose.CH_MODAL
# Disable the timeout
old = _ida_idaapi.set_script_timeout(0)
n = _ida_kernwin.choose_choose(self)
_ida_idaapi.set_script_timeout(old)
with disabled_script_timeout_t():
n = _ida_kernwin.choose_choose(self)
# Delete the modal chooser instance
self.Close()
+18 -9
View File
@@ -46114,6 +46114,24 @@ detach_action_from_toolbar(*args)
@param name: the action name (C++: const char *)
@return: success
Help on class disabled_script_timeout_t in module ida_kernwin:
class disabled_script_timeout_t(__builtin__.object)
| Methods defined here:
|
| __enter__(self)
|
| __exit__(self, type, value, tb)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
Help on class disasm_line_t in module ida_kernwin:
class disasm_line_t(__builtin__.object)
@@ -73313,15 +73331,6 @@ LoadFile(filepath, pos, ea, size)
Help on function MakeVar in module idc:
MakeVar(ea)
Mark the location as "variable"
@param ea: address to mark
@return: None
@note: All that IDA does is to mark the location as "variable".
Nothing else, no additional analysis is performed.
This function may disappear in the future.
Help on function SaveFile in module idc:
+18 -9
View File
@@ -46249,6 +46249,24 @@ detach_action_from_toolbar(*args) -> 'bool'
@param name: the action name (C++: const char *)
@return: success
Help on class disabled_script_timeout_t in module ida_kernwin:
class disabled_script_timeout_t(builtins.object)
| Methods defined here:
|
| __enter__(self)
|
| __exit__(self, type, value, tb)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
Help on class disasm_line_t in module ida_kernwin:
class disasm_line_t(builtins.object)
@@ -73351,15 +73369,6 @@ LoadFile(filepath, pos, ea, size)
Help on function MakeVar in module idc:
MakeVar(ea)
Mark the location as "variable"
@param ea: address to mark
@return: None
@note: All that IDA does is to mark the location as "variable".
Nothing else, no additional analysis is performed.
This function may disappear in the future.
Help on function SaveFile in module idc:
+6 -6
View File
@@ -42,12 +42,12 @@ extern plugin_t PLUGIN;
%ignore ask_text;
%ignore vwarning;
// Note: don't do that for ask_form(), since that calls back into Python.
%thread ask_addr;
%thread ask_seg;
%thread ask_long;
%thread ask_yn;
%thread ask_buttons;
%thread ask_file;
%modal_dialog_triggering_function(ask_addr);
%modal_dialog_triggering_function(ask_seg);
%modal_dialog_triggering_function(ask_long);
%modal_dialog_triggering_function(ask_yn);
%modal_dialog_triggering_function(ask_buttons);
%modal_dialog_triggering_function(ask_file);
%ignore simpleline_t::simpleline_t(const qstring &);
+15
View File
@@ -1681,6 +1681,21 @@ SWIGINTERN bool __chkreqidb()
%}
%define %modal_dialog_triggering_function(NAME)
%thread NAME;
%pythonprepend NAME
%{
import ida_kernwin
# kludge: we can't use %feature("shadow") for top-level
# functions (see https://github.com/swig/swig/issues/980)
# Thus we'll %pythonprepend some code, and return from it,
# making the original code unreachable. Not pretty, but I
# don't have anything better at the moment.
with ida_kernwin.disabled_script_timeout_t():
return _ida_kernwin.NAME(*args)
%}
%enddef
%include <constraints.i>
// If the module is 'pro', don't import pro.h, or the %include