From f7e52a0c3076e60ef30b1ebe0479d500ea8a2de2 Mon Sep 17 00:00:00 2001 From: Arnaud Diederen Date: Mon, 9 Dec 2019 10:10:26 +0100 Subject: [PATCH] Backported fixes --- idapyswitch_linux.cpp | 27 ++++++++++++------- idapyswitch_win.cpp | 11 +++++--- idapython.cpp | 39 ++++++++++++++++++++++----- out_of_tree/parsed_notifications.zip | Bin 4187558 -> 4187558 bytes python/idc.py | 24 +++++------------ pywraps.cpp | 30 ++++++++++++--------- pywraps.hpp | 4 ++- pywraps/py_kernwin.py | 9 +++++++ pywraps/py_kernwin_askform.py | 5 +--- pywraps/py_kernwin_choose.py | 5 ++-- release_pydoc_injections2.txt | 27 ++++++++++++------- release_pydoc_injections3.txt | 27 ++++++++++++------- swig/kernwin.i | 12 ++++----- tools/deploy/header.i.in | 15 +++++++++++ 14 files changed, 154 insertions(+), 81 deletions(-) diff --git a/idapyswitch_linux.cpp b/idapyswitch_linux.cpp index 643e86d..73c6537 100644 --- a/idapyswitch_linux.cpp +++ b/idapyswitch_linux.cpp @@ -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 diff --git a/idapyswitch_win.cpp b/idapyswitch_win.cpp index 0c2f9ac..22fe902 100644 --- a/idapyswitch_win.cpp +++ b/idapyswitch_win.cpp @@ -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 = ""; + 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 = ""; + } } - for ( auto path : paths ) + for ( const qstring &path : paths ) if ( path.find(appx_path) != qstring::npos ) return true; diff --git a/idapython.cpp b/idapython.cpp index 90e95b5..11f5cc5 100644 --- a/idapython.cpp +++ b/idapython.cpp @@ -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; diff --git a/out_of_tree/parsed_notifications.zip b/out_of_tree/parsed_notifications.zip index d68c926f36cff1df4de65abe6ce199cc58dc0198..65a22ad3b589a4cb3349ec25ea4f7df07a6a8b77 100644 GIT binary patch delta 41293 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 delta 41293 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�D z^EqA_Jit}yN4#Y|BHS9*1Q@*rpCN<~ndbbC{d1v2_)>1r&-hk2)?5B-&C$kUPEP;S zbrv4EXi5l!e#ZclG!W>PPzI+Cb;1(l-hwO+OBjZB@GG4ldm!mvIw2CRCPXJF$>LFT z!dc9@+u{?H0`Mh1AqBg;gsKUOUyZMt&Ln;=s)&q)M|h&}Zkr%$7YA`&+a{dy z6?3NT!_vX$A!q(+#__ZGimgZg1g(^f@nc$Z`zKt(WY=vlLwd*Hgu>4cRvXSRnl(J3 zD^`Jj$0jI!SG92o;TVSfrY0ySxua7P;8TCpbsx@3P<#n~m{$x}XUtDfzBMp!enR^y z;_6Q~L0ZX9;ty9_+)5}?n0p^4D2JU>4--mZg%8jEqHzXk-xU7prsRhNxtAeH9})sk z#^(QkF{Em=`k#bU^wJmK7#mgip3oTCo2E)s41H6TxCG1n5Vu5SYJSiyF$(kUpPEGF z-W0AZHe*V7>y;>rF2L!`pETAc7Jhl`x=*6w1i|`5fTP)DBBj zbh{)haSU1_xJ;trGF{3f&cW4R%Q4_8pTiPzD~E~F;Pm0f;6 z;!P4OC+^3N;7ip+MftVTBo5BjPE?xAQgsrSA-Ypd6?DYdEHN2pUZcV?ODut^(hfd6 zKtIAfu~ninv4s~+yRlR?Y0vD2X&O9XqKS8JCq~O~*B^|l%XLdslHjOri4~BA?E@2) z&P@FFp8KH0qL{*?MkgviCmAz3u_hY*%p`>X-o3|6PJD(s4V=d4wDYvYTFzp9dH7?s ztrPr0;#yxSQQ@H>?x;gkOT*Jd3^NkDd3y;~mlS-qa4joLA`;2UT zV>2mwC<%UROT#_sc#_iePClMA5M};xF)2feKFmH{E+rNICPjZONqMKy$pLTfWMc^G-JRZYZXHBbK0|XqU!&m6F&Nvi2awH~GRewNXIPo! z3&>sVUy|ifC&~UL`2^;dmI=v;s!?vFjAUlOdAieuZPz2a5NuDNtDWLz-WifpfdCqKs4~7Ji(a)1xV4k}3GFd5ep|6tR zAuP?E$py(u7csLS`3SDgc%Q5U%(C~%C(&eGKQboU`7wDNDx}Rfg)Uk54IEk&`lX9a zZga#hCDl^dY9rYN?lvViKXD|McNMIST-p=_Mc6Vs@le*)3;p(qnh<)Y|49S7&V_j7N^82ED|`f8?iTe zk!X{xPvVnog`L>2YBuGlbfTJV27aJndP127@1Q#^QUu@fwY%-`%%7~NVe>>qZArJu z)s%cmw|QXs+uO`-Xgq}JARqqgUWpBD^4GoSRKlMOYG{i`=h@c8raWvBRikfe>xSpf zk?n0*st@j=0XAqpnqG1RsjO7 z7V-wCcnaT#*_4k6>WAB2VEX?$&Zdl)>yEd<6G@u-?@wmXM@_Mn!d$j3bKdB(Aaw~( zEc#QjY)a8zk!7oaV*WYTrpySd&9kMU2W1J0Dh2qkU=aBv*b0BOJavikZ{*4nTYq%w z8q2}hQmD^cZd-s+Q)Yur&T%*;n!3SO8oOyiZ1V77_a5pVG-xab74OA6(jfNXpm)RZOYi-%~_i#s^;rO;8eVD9;`yy%N-f7-hDQ9F35`8mi(^kEmImguBqLMT|+rM z*oxI5rCzpmN?XTWTU)cV=&n+2c)Krc!%9lmnA@hbaMbGDwxA!GXS&9@T}pFDE01i) zTe+ZJN_EFIP200;D9`!rdCUnNK&!GJ(lxmqQkp8%DWr5qUeYZcQ#v@Vsn7}Z<(ckk+=Z2tLQZx`X{q3$w5oPxtxVVK z?aKNpT~nqT>tl4yx^BF^Lb`*bvc~9|Io(<66pu@fl*WoSC}dak$UhGD+T90ucED4nFP~c$_GL9s z`7!oOX|Ld+keq%gbrlHZ(5-(;E5#NRGNC`npuJA!DExK#LAXd*5Vi?SO@A$zGxiW`z&6mNfO)2I+L)bMG@@xob z-eFgVp*)AzhVuEa$}o`B!RPl3V?C2%EZqhTBLU z^RSV;=KmVWM?vN&u&D#)Yol17r?je%<}vRd&90$5ml?zAkV4js0c|)~(043rWr}&^ zSQZb36#NgQ-8k@YnL~>C(KuG~6w+usYj=w0+;}#Y>6(-YtS3;&)(LFHQAml2DXkrO zUNw=|v+pF{UNa~0va2TZ{EVE;>+s!VzJg>HR5CL1Z0L4qHrRV~0X6Ol7q} zWv@Jq)hb=Ha~fN7>6)17fJdf9AseQ%`H=1^HX{Z82g;<*fkLuoz#0dLdL}D7#WQLq z?{)8H@>2Ai1zL5$b9WXmSN$xgjPe?a`D_+Q;SecxX7jQip3Ulz?uwhk+iUwA);d(K z$hj;Y3Ryark3r)+-hxx+f$R=C{5g-6ol@_Y&0G0Jc1mYO3c9BEudL=N@5RYnASbT)_Gdg)E^E2h6&K>>A3? z*oC~kzAfZ6)@KpWlJU@8cNeiyNomzx%xmn}Vzz&#yUH%%tKQZnypKgKWvxsxuUX3T zV_nADi(;O!jQ4QWa*$Nk7+o`HInVR+<-7&ktl%+UTEW&+%1@(}yl0+Y$y2Yk3V4>O z(_Q;k!5UeI6!ObzkkkRPX*F-Jpfy0tVU4f`a-9sJa#?<3bx1MK`wb$_VU6!vUKfcTtFD z6I=A?uECqwu%M8?HvvBmiqG84hx@(FtXvdx{VmXZIRw*{Ex@4+p_uFZ&U1L^ceWj) zYa+MuYnE)~wV~MtNy5Q6leY2N__>XBABwsEc7DyD+xbM&VF#ONsa%hDusWo88svgQ z$@-y?v$;H;Dm!79%pt{-yOVW!3MsRTZD}cF<1YRHU3xd@N7f--vtT!`c`X6CWLlJ; zNraW1?)sOoQcy^@J#0dvkn4L`%oIIF z5p{sq*y0218p@CHU`i)N^Az*KgTSGKe!LFx)W;kGpO@EAJOzjNqh9~R|Kl5n+2E$T zy5zBTr_>+i@jTZ*0@P(&&^0HH@cKzT%JZCil$Dh3iaN#~d@1!`kFiG(3Q-+rIi$PB z9A`1pHSdq}a&FHtwiS^3DK72U#kf1wI`h z>(BC93O&bX=>_L_y{XUhw8oz2IedGbFJfITus%aMymJBK#etue7y0)5_C;RO^h^Aa z>)0heC#PLjbc;GXaGCXLO10?TZh#lbQAXF?q!3wS6m!j+Y$Hk6oV>|5+R3+g$o5;jy^7uj{m8T^ z=0&%8tp?uVJz@GCHoH>lpXnNzLkj79m(>P^+`r3L-un0W>~ZcMuhrE1Y#yL^4&LYS zlz#v=b&z7)1J)C$T%{iJS!nq~*2)yK`4OyfkYd&&z9H2;W-UlDPkPMqOdyLBP3>pw8VWi1jIXNp=RB=l&smL8NyA^TO+AIIe!<5@ ziI*UkgA~F`zNVXA@ng=}uXqlfU$c3G@;u@-Z}-oy*#DirX(v7vzHC*UowpT%$4&W&PLzhm@()#Be zPpj8^mKI&};C~?XKk#dgeSnB_uug@)c|ZK^Z?Kocn&KaM>We;tKg(+<&xU`1mdrDS zO!$Y-BwzmFGg7xtU<(I44?eL6BZ{ZPXI6(4^7u2K{n~zEIizcDd|_jd>ZjSitW7B- z|6kS2jondI)!xp$!17O>;6yPf(`y-wL#aM{*R>vc;+YD9q&TsZ?|(NoRZG=8j3C` zmMmvGa|K4ZadEM8HD-W|og2`7bg?sID~hMD%FYcrU#sj~+_rNCJPwjSa%DNB)El|k znejWte8$br^}aSWPXZxk`|w5AzZDJaiB{s+>}WM{5E>6%w2Uak&i-lmt#Kufj--IZ#ww|CUxaSO{c zT~pD|&Rh*sDfal;dpT;gx)s9I0rLSX>l+l$FGYa5Y%hvuRS{le7Jr_@$^Le3;Nup+ z?;1uS4%FWSu>4S39RdN5?DLeLM}fSD*9`)#%4_JZ6G5O28A5l(1w&4drJ#`Q!FJ|q zk3!0Zu(DG;YeIN$2`b9cqPyl7W%WZLZpFY`9B2(K2ACZn1;u!KwJXl=x>B5t6v|Jn z61+C@OR&4>n&gu9YKrWl6eanLWDd1AS2R!8%n1dLk~Kyl#xU?72gv*|HfK^vEv48@ zOCfVgK|YivrFgXAeC&(~=RM(X3UTm+E)lGLD4tspKuhL_(rOsVuQ?IPudzqjJ1P9o zT_>X0OiMAxlm<_bF;mF)(yTVH0>?}nB`q`O>$XYifv`t{6p6Sm1Av6A-|Sm zy^caW%k#U2lxHQSYhIOSX;GeAS77x_*IcZ?@2dO@yNj;b{R_K>;t7xD>*<!LF25=~^(j@@Sf;z2tMXPJS(T+u z*Lp!;$WRowd~wQo@;IJOoui7Yx7zCO>JKGHg)(YxLk*irW$p5%^$7H zuA%ygPv>>GF`dU8T#wZTm2^%$u(Iq?fF~z|SK-(U*2r|zw+uen^sdjUkh1f#KHF|k zNS6jII}~!K0nc*XhEOUURJf}li3OPn0GS8I5 z*sg5lrjX4J5W1^GHc{h3qdyxKl=`9mY>z^Bl^(#?*KGsXHFQ_-Kwi?Efvgl1 zkA4vAEfg|-5X&>g^Uok2Pp`qCF$dZ24`$D7bXTn*tbQoweM5L3t1y(e>B^zJ?0&=e zy0~l@%MZnD8O}>FbvUe%JptC_i~!@v0LtLN5qySvGlFm3JB?%&Mt9vG$s4)BC|Kiw z`RpiO8S$feJUd47f`*Ub6}DguZwjxmAgF^IjvC8irpov{mJLD5bN_LCLt8KoXvui! zt~TTOBhsDmd`@pVf!#$hpPazAD6tb+If<7dXA&=kelnW?D4ubXSfJ!lN3L9Q@&6_DaKb@ztcBi}UPvtv+*3)=em!?5;C~J&jPM*%%i$XR}XQiN! zuo*m_MKf3(QtF;F`B2W9$@|aOnLMrTvv~h`IE$5(Vs4hj1%Yrei$CDkpAF$9hcexD zb2h&#V-9Nzy5`6nHsGkF(Q}~`9yolGv;zhiNn-;S^Mt4nJ%+BU1hd&kr z9+@AyX7~~w^XDbJR=X`_qnqx!u@s`ff#=H0?3s#{>6+8a*#4DLue%&%lq> zkl)v{a?v$qHt_tc-N0sJx+Z8NFX^0(>@K>-V-xRDqc`yyE7-(0GOag*6te78t_z#_ zsI0z)Z~cyL0Sh|F75_V{F^Xry?>wGjTX{V%-O9_Q-^Sw^w~f^^#r*d+kli6tdT!_C zy0e}4x_UcUJXB*xcJQ=*$z`)2rL{hntrv7x@twS$g`MnBg06Ad#am~@F23S_+Qsri zX?5KV+HjET4u!~irfbp(uhl;YpV?yfu;UKOPwpO;X9@}5%gRn63-{WOIMN!qkCmNL z|FrLac;3%LZtsU7tt6PIqlM z%tjN16wPBR2!+hbgG}oX1)fKEJX4Rbl2R$Y9szzFtke4_8*vo#{iAHlPj}Th#%i9f zIe3icFy=Ve)Io=V)&|PEx;4v5c0sJ`7YI~B8f@>#% zLwSuT#VOvyPn-hJbkK$^A0Q4|-IdR4qr_?66PBIkE1LEUpKZpU;rrg7XFv)ET7Ay4 zwxB#eILm83;~cA1y5{IPK2qY&vmDYjJI?cxMqc1)ExN$lLU$1`%N$ZX6E5;K<;g)*Wi)$Cr7z8eQReK6`~-LwBWIW%Cb(Y`@B8S_+B0#(Tob zYpllT8q0MSGv#pVbv}=MyUzQ3{~Mq~Sw9rd;~T6eP)Np2-sk_g$zrCo5^k{?qq}l% z0f(|yDJ1+hi-$s%-R5(P?;X&p%n!vp?+)vSbeH>GHj~gbgYL4Gh(ey;<#)BX$IE`{ z9{97&A>CE?KELbOeU?MIChh@$D%t;lT|+r6_mGFIeh3#o?!{|InX$S9k`V06+5<#y+!$ F{U5pfVUYj; diff --git a/python/idc.py b/python/idc.py index 9c6297c..a9971bd 100644 --- a/python/idc.py +++ b/python/idc.py @@ -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 diff --git a/pywraps.cpp b/pywraps.cpp index 14af288..477161c 100644 --- a/pywraps.cpp +++ b/pywraps.cpp @@ -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: diff --git a/pywraps.hpp b/pywraps.hpp index 59390e4..074f485 100644 --- a/pywraps.hpp +++ b/pywraps.hpp @@ -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) ) diff --git a/pywraps/py_kernwin.py b/pywraps/py_kernwin.py index 90d6f1a..ef9fcbe 100644 --- a/pywraps/py_kernwin.py +++ b/pywraps/py_kernwin.py @@ -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 diff --git a/pywraps/py_kernwin_askform.py b/pywraps/py_kernwin_askform.py index 9277cae..c78e92e 100644 --- a/pywraps/py_kernwin_askform.py +++ b/pywraps/py_kernwin_askform.py @@ -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): diff --git a/pywraps/py_kernwin_choose.py b/pywraps/py_kernwin_choose.py index 6da1234..e0b0743 100644 --- a/pywraps/py_kernwin_choose.py +++ b/pywraps/py_kernwin_choose.py @@ -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() diff --git a/release_pydoc_injections2.txt b/release_pydoc_injections2.txt index a649484..076c81c 100644 --- a/release_pydoc_injections2.txt +++ b/release_pydoc_injections2.txt @@ -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: diff --git a/release_pydoc_injections3.txt b/release_pydoc_injections3.txt index adf4b2a..596cc06 100644 --- a/release_pydoc_injections3.txt +++ b/release_pydoc_injections3.txt @@ -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: diff --git a/swig/kernwin.i b/swig/kernwin.i index 36ccd6a..af6efcd 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -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 &); diff --git a/tools/deploy/header.i.in b/tools/deploy/header.i.in index 5af0dc3..6047753 100644 --- a/tools/deploy/header.i.in +++ b/tools/deploy/header.i.in @@ -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 // If the module is 'pro', don't import pro.h, or the %include