From 3b433195716732f63f352730d481a0a9415639a1 Mon Sep 17 00:00:00 2001 From: negasora Date: Mon, 11 Jun 2018 19:03:18 -0400 Subject: Add empty list properties to some classes to allow for visibility --- python/architecture.py | 5 +++++ python/binaryview.py | 4 ++++ python/platform.py | 5 +++++ python/plugin.py | 10 ++++++++++ python/scriptingprovider.py | 5 +++++ python/transform.py | 5 +++++ python/update.py | 4 ++++ 7 files changed, 38 insertions(+) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index c5f87ec6..df22da7f 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -391,6 +391,11 @@ class Architecture(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @property def full_width_regs(self): """List of full width register strings (read-only)""" diff --git a/python/binaryview.py b/python/binaryview.py index 0cf25e70..80298304 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -341,6 +341,10 @@ class BinaryViewType(object): if not isinstance(value, BinaryViewType): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass @property def name(self): diff --git a/python/platform.py b/python/platform.py index a79e3b9a..dd756178 100644 --- a/python/platform.py +++ b/python/platform.py @@ -120,6 +120,11 @@ class Platform(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @property def default_calling_convention(self): """ diff --git a/python/plugin.py b/python/plugin.py index 30a46412..13ca51af 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -83,6 +83,11 @@ class PluginCommand(object): self.description = str(cmd.description) self.type = PluginCommandType(cmd.type) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @classmethod def _default_action(cls, view, action): try: @@ -587,6 +592,11 @@ class BackgroundTask(object): def __del__(self): core.BNFreeBackgroundTask(self.handle) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @property def progress(self): """Text description of the progress of the background task (displayed in status bar of the UI)""" diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 988f856d..1e2338d9 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -303,6 +303,11 @@ class ScriptingProvider(object): if handle is not None: self.handle = core.handle_of_type(handle, core.BNScriptingProvider) self.__dict__["name"] = core.BNGetScriptingProviderName(handle) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + def register(self): self._cb = core.BNScriptingProviderCallbacks() diff --git a/python/transform.py b/python/transform.py index 59d719e7..3284ed74 100644 --- a/python/transform.py +++ b/python/transform.py @@ -200,6 +200,11 @@ class Transform(object): log.log_error(traceback.format_exc()) return False + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @abc.abstractmethod def perform_decode(self, data, params): if self.type == TransformType.InvertingTransform: diff --git a/python/update.py b/python/update.py index 1eb8ea61..2f817595 100644 --- a/python/update.py +++ b/python/update.py @@ -115,6 +115,10 @@ class UpdateChannel(object): self.name = name self.description = desc self.latest_version_num = ver + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass @property def versions(self): -- cgit v1.3.1 From 829917b3bb442d58dbd5f95dc13634ddb7a02a51 Mon Sep 17 00:00:00 2001 From: negasora Date: Mon, 11 Jun 2018 19:05:21 -0400 Subject: fix styling --- python/binaryview.py | 1 + python/scriptingprovider.py | 1 + python/update.py | 1 + 3 files changed, 3 insertions(+) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 80298304..81851c1f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -341,6 +341,7 @@ class BinaryViewType(object): if not isinstance(value, BinaryViewType): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def list(self): """Allow tab completion to discover metaclass list property""" diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 1e2338d9..9cacc6ad 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -303,6 +303,7 @@ class ScriptingProvider(object): if handle is not None: self.handle = core.handle_of_type(handle, core.BNScriptingProvider) self.__dict__["name"] = core.BNGetScriptingProviderName(handle) + @property def list(self): """Allow tab completion to discover metaclass list property""" diff --git a/python/update.py b/python/update.py index 2f817595..a89c9348 100644 --- a/python/update.py +++ b/python/update.py @@ -115,6 +115,7 @@ class UpdateChannel(object): self.name = name self.description = desc self.latest_version_num = ver + @property def list(self): """Allow tab completion to discover metaclass list property""" -- cgit v1.3.1 From 811544620f903b137aeb7660183ca9d6bb0d7590 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Wed, 20 Jun 2018 16:03:27 -0400 Subject: Add DownloadProvider Support. --- binaryninjaapi.cpp | 18 ---- binaryninjaapi.h | 60 ++++++++++++- binaryninjacore.h | 43 +++++++++- docs/about/open-source.md | 6 -- downloadprovider.cpp | 135 +++++++++++++++++++++++++++++ python/__init__.py | 1 + python/downloadprovider.py | 210 +++++++++++++++++++++++++++++++++++++++++++++ python/pluginmanager.py | 3 + 8 files changed, 447 insertions(+), 29 deletions(-) create mode 100644 downloadprovider.cpp create mode 100644 python/downloadprovider.py (limited to 'python') diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index f5eede03..b774cf2b 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -344,21 +344,3 @@ string BinaryNinja::GetUniqueIdentifierString() BNFreeString(str); return result; } - - -string BinaryNinja::GetLinuxCADirectory() -{ - char* str = BNGetLinuxCADirectory(); - string result = str; - BNFreeString(str); - return result; -} - - -string BinaryNinja::GetLinuxCABundlePath() -{ - char* str = BNGetLinuxCABundlePath(); - string result = str; - BNFreeString(str); - return result; -} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 7a13118f..9c0b9bc4 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -3636,6 +3636,63 @@ namespace BinaryNinja const std::string& autoTypeSource = ""); }; + // DownloadProvider + class DownloadProvider; + + class DownloadInstance: public CoreRefCountObject + { + protected: + DownloadInstance(DownloadProvider* provider); + DownloadInstance(BNDownloadInstance* instance); + + static void DestroyInstanceCallback(void* ctxt); + static int PerformRequestCallback(void* ctxt, const char* url); + + virtual void DestroyInstance(); + + public: + virtual int PerformRequest(const std::string& url) = 0; + + int PerformRequest(const std::string& url, BNDownloadInstanceOutputCallbacks* callbacks); + + std::string GetError() const; + void SetError(const std::string& error); + }; + + class CoreDownloadInstance: public DownloadInstance + { + public: + CoreDownloadInstance(BNDownloadInstance* instance); + + virtual int PerformRequest(const std::string& url) override; + }; + + class DownloadProvider: public StaticCoreRefCountObject + { + std::string m_nameForRegister; + + protected: + DownloadProvider(const std::string& name); + DownloadProvider(BNDownloadProvider* provider); + + static BNDownloadInstance* CreateInstanceCallback(void* ctxt); + + public: + virtual Ref CreateNewInstance() = 0; + + static std::vector> GetList(); + static Ref GetByName(const std::string& name); + static void Register(DownloadProvider* provider); + }; + + class CoreDownloadProvider: public DownloadProvider + { + public: + CoreDownloadProvider(BNDownloadProvider* provider); + virtual Ref CreateNewInstance() override; + }; + + // Scripting Provider class ScriptingOutputListener { BNScriptingOutputListener m_callbacks; @@ -3994,7 +4051,4 @@ namespace BinaryNinja bool IsArray() const; bool IsKeyValueStore() const; }; - - std::string GetLinuxCADirectory(); - std::string GetLinuxCABundlePath(); } diff --git a/binaryninjacore.h b/binaryninjacore.h index e4d3a919..e4fb9de2 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -120,6 +120,8 @@ extern "C" struct BNArchitecture; struct BNFunction; struct BNBasicBlock; + struct BNDownloadProvider; + struct BNDownloadInstance; struct BNFunctionGraph; struct BNFunctionGraphBlock; struct BNSymbol; @@ -1483,6 +1485,27 @@ extern "C" size_t count, total; }; + struct BNDownloadInstanceOutputCallbacks + { + uint64_t (*writeCallback)(uint8_t* data, uint64_t len, void* ctxt); + void* writeContext; + bool (*progressCallback)(void* ctxt, uint64_t progress, uint64_t total); + void* progressContext; + }; + + struct BNDownloadInstanceCallbacks + { + void* context; + void (*destroyInstance)(void* ctxt); + int (*performRequest)(void* ctxt, const char* url); + }; + + struct BNDownloadProviderCallbacks + { + void* context; + BNDownloadInstance* (*createInstance)(void* ctxt); + }; + enum BNFindFlag { NoFindFlags = 0, @@ -3195,6 +3218,24 @@ extern "C" char*** outVarName, size_t* outVarNameElements); + // Download providers + BINARYNINJACOREAPI BNDownloadProvider* BNRegisterDownloadProvider(const char* name, BNDownloadProviderCallbacks* callbacks); + BINARYNINJACOREAPI BNDownloadProvider** BNGetDownloadProviderList(size_t* count); + BINARYNINJACOREAPI void BNFreeDownloadProviderList(BNDownloadProvider** providers); + BINARYNINJACOREAPI BNDownloadProvider* BNGetDownloadProviderByName(const char* name); + + BINARYNINJACOREAPI char* BNGetDownloadProviderName(BNDownloadProvider* provider); + BINARYNINJACOREAPI BNDownloadInstance* BNCreateDownloadProviderInstance(BNDownloadProvider* provider); + + BINARYNINJACOREAPI BNDownloadInstance* BNInitDownloadInstance(BNDownloadProvider* provider, BNDownloadInstanceCallbacks* callbacks); + BINARYNINJACOREAPI BNDownloadInstance* BNNewDownloadInstanceReference(BNDownloadInstance* instance); + BINARYNINJACOREAPI void BNFreeDownloadInstance(BNDownloadInstance* instance); + BINARYNINJACOREAPI int BNPerformDownloadRequest(BNDownloadInstance* instance, const char* url, BNDownloadInstanceOutputCallbacks* callbacks); + BINARYNINJACOREAPI uint64_t BNWriteDataForDownloadInstance(BNDownloadInstance* instance, uint8_t* data, uint64_t len); + BINARYNINJACOREAPI bool BNNotifyProgressForDownloadInstance(BNDownloadInstance* instance, uint64_t progress, uint64_t total); + BINARYNINJACOREAPI char* BNGetErrorForDownloadInstance(BNDownloadInstance* instance); + BINARYNINJACOREAPI void BNSetErrorForDownloadInstance(BNDownloadInstance* instance, const char* error); + // Scripting providers BINARYNINJACOREAPI BNScriptingProvider* BNRegisterScriptingProvider(const char* name, BNScriptingProviderCallbacks* callbacks); @@ -3460,8 +3501,6 @@ extern "C" BINARYNINJACOREAPI BNMetadata* BNBinaryViewQueryMetadata(BNBinaryView* view, const char* key); BINARYNINJACOREAPI void BNBinaryViewRemoveMetadata(BNBinaryView* view, const char* key); - BINARYNINJACOREAPI char* BNGetLinuxCADirectory(); - BINARYNINJACOREAPI char* BNGetLinuxCABundlePath(); #ifdef __cplusplus } #endif diff --git a/docs/about/open-source.md b/docs/about/open-source.md index b0a35f37..be9725d0 100644 --- a/docs/about/open-source.md +++ b/docs/about/open-source.md @@ -22,13 +22,11 @@ The previous tools are used in the generation of our documentation, but are not * Core - [discount] ([discount license] - BSD) - - [libcurl] ([libcurl license] - MIT/X derivative) - [libgit2] ([libgit2 license] - GPLv2 with linking exception) - [libmspack] ([libmspack license] - LGPL, v2) - [llvm] ([llvm license] - BSD-style) - [lzf] ([lzf license] - BSD) - [jemalloc] ([jemalloc license] - BSD) - - [openssl] ([openssl license] - openssl license) - [sqlite] ([sqlite license] - public domain) - [zlib] ([zlib license] - zlib license) @@ -69,8 +67,6 @@ Please note that we offer no support for running Binary Ninja with modified Qt l [discount]: http://www.pell.portland.or.us/~orc/Code/discount/ [doxygen license]: https://github.com/doxygen/doxygen/blob/master/LICENSE [doxygen]: http://www.stack.nl/~dimitri/doxygen/ -[libcurl]: https://curl.haxx.se/ -[libcurl license]: https://curl.haxx.se/docs/copyright.html [libgit2]: https://libgit2.github.com/ [libgit2 license]: https://github.com/libgit2/libgit2/blob/master/COPYING [libmspack]: https://www.cabextract.org.uk/libmspack/ @@ -87,8 +83,6 @@ Please note that we offer no support for running Binary Ninja with modified Qt l [mkdocs]: http://www.mkdocs.org/ [opensans license]: http://www.apache.org/licenses/LICENSE-2.0.html [opensans]: https://www.google.com/fonts/specimen/Open+Sans -[openssl license]: https://www.openssl.org/source/license.html -[openssl]: https://www.openssl.org/ [qt license]: https://www.qt.io/qt-licensing-terms/ [qt]: https://www.qt.io/download/ [sourcecodepro license]: https://github.com/adobe-fonts/source-code-pro/blob/master/LICENSE.txt diff --git a/downloadprovider.cpp b/downloadprovider.cpp new file mode 100644 index 00000000..0e3483df --- /dev/null +++ b/downloadprovider.cpp @@ -0,0 +1,135 @@ +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + + +DownloadInstance::DownloadInstance(DownloadProvider* provider) +{ + BNDownloadInstanceCallbacks cb; + cb.context = this; + cb.destroyInstance = DestroyInstanceCallback; + cb.performRequest = PerformRequestCallback; + m_object = BNInitDownloadInstance(provider->GetObject(), &cb); +} + + +DownloadInstance::DownloadInstance(BNDownloadInstance* instance) +{ + m_object = instance; +} + + +void DownloadInstance::DestroyInstanceCallback(void* ctxt) +{ + DownloadInstance* instance = (DownloadInstance*)ctxt; + instance->DestroyInstance(); +} + + +int DownloadInstance::PerformRequestCallback(void* ctxt, const char* url) +{ + DownloadInstance* instance = (DownloadInstance*)ctxt; + return instance->PerformRequest(url); +} + + +string DownloadInstance::GetError() const +{ + char* str = BNGetErrorForDownloadInstance(m_object); + string result = str; + BNFreeString(str); + return result; +} + + +void DownloadInstance::SetError(const string& error) +{ + BNSetErrorForDownloadInstance(m_object, error.c_str()); +} + + +int DownloadInstance::PerformRequest(const string& url, BNDownloadInstanceOutputCallbacks* callbacks) +{ + return BNPerformDownloadRequest(m_object, url.c_str(), callbacks); +} + + +void DownloadInstance::DestroyInstance() +{ +} + + +CoreDownloadInstance::CoreDownloadInstance(BNDownloadInstance* instance): DownloadInstance(instance) +{ +} + + +int CoreDownloadInstance::PerformRequest(const std::string& url) +{ + (void)url; + return -1; +} + + +DownloadProvider::DownloadProvider(const string& name): m_nameForRegister(name) +{ +} + + +DownloadProvider::DownloadProvider(BNDownloadProvider* provider) +{ + m_object = provider; +} + + +BNDownloadInstance* DownloadProvider::CreateInstanceCallback(void* ctxt) +{ + DownloadProvider* provider = (DownloadProvider*)ctxt; + Ref instance = provider->CreateNewInstance(); + return instance ? BNNewDownloadInstanceReference(instance->GetObject()) : nullptr; +} + + +vector> DownloadProvider::GetList() +{ + size_t count; + BNDownloadProvider** list = BNGetDownloadProviderList(&count); + vector> result; + for (size_t i = 0; i < count; i++) + result.push_back(new CoreDownloadProvider(list[i])); + BNFreeDownloadProviderList(list); + return result; +} + + +Ref DownloadProvider::GetByName(const string& name) +{ + BNDownloadProvider* result = BNGetDownloadProviderByName(name.c_str()); + if (!result) + return nullptr; + return new CoreDownloadProvider(result); +} + + +void DownloadProvider::Register(DownloadProvider* provider) +{ + BNDownloadProviderCallbacks cb; + cb.context = provider; + cb.createInstance = CreateInstanceCallback; + provider->m_object = BNRegisterDownloadProvider(provider->m_nameForRegister.c_str(), &cb); +} + + +CoreDownloadProvider::CoreDownloadProvider(BNDownloadProvider* provider): DownloadProvider(provider) +{ +} + + +Ref CoreDownloadProvider::CreateNewInstance() +{ + BNDownloadInstance* result = BNCreateDownloadProviderInstance(m_object); + if (!result) + return nullptr; + return new CoreDownloadInstance(result); +} diff --git a/python/__init__.py b/python/__init__.py index 729e4f8a..fda5f297 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -50,6 +50,7 @@ from .lineardisassembly import * from .undoaction import * from .highlight import * from .scriptingprovider import * +from .downloadprovider import * from .pluginmanager import * from .setting import * from .metadata import * diff --git a/python/downloadprovider.py b/python/downloadprovider.py new file mode 100644 index 00000000..4756fd90 --- /dev/null +++ b/python/downloadprovider.py @@ -0,0 +1,210 @@ +# Copyright (c) 2015-2018 Vector 35 LLC +# +# 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 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. + + +import abc +import code +import ctypes +import sys +import traceback + +try: + from urllib.parse import urlparse, urlencode + from urllib.request import urlopen, Request, build_opener, install_opener, ProxyHandler + from urllib.error import HTTPError, URLError +except ImportError: + from urlparse import urlparse + from urllib import urlencode + from urllib2 import urlopen, Request, build_opener, install_opener, ProxyHandler, HTTPError, URLError + +# Binary Ninja Components +import _binaryninjacore as core +from binaryninja.setting import Setting +import startup +import log + + +class DownloadInstance(object): + def __init__(self, provider, handle = None): + if handle is None: + self._cb = core.BNDownloadInstanceCallbacks() + self._cb.context = 0 + self._cb.destroyInstance = self._cb.destroyInstance.__class__(self._destroy_instance) + self._cb.performRequest = self._cb.performRequest.__class__(self._perform_request) + self.handle = core.BNInitDownloadInstance(provider.handle, self._cb) + else: + self.handle = core.handle_of_type(handle, core.BNDownloadInstance) + self._outputCallbacks = None + + def __del__(self): + core.BNFreeDownloadInstance(self.handle) + + def _destroy_instance(self, ctxt): + try: + self.perform_destroy_instance() + except: + log.log_error(traceback.format_exc()) + + def _perform_request(self, ctxt, url): + try: + return self.perform_request(ctxt, url) + except: + log.log_error(traceback.format_exc()) + return -1 + + @abc.abstractmethod + def perform_destroy_instance(self): + raise NotImplementedError + + @abc.abstractmethod + def perform_request(self, ctxt, url): + raise NotImplementedError + + def perform_request(self, url, callbacks): + return core.BNPerformDownloadRequest(self.handle, url, callbacks) + + +class _DownloadProviderMetaclass(type): + @property + def list(self): + """List all DownloadProvider types (read-only)""" + startup._init_plugins() + count = ctypes.c_ulonglong() + types = core.BNGetDownloadProviderList(count) + result = [] + for i in xrange(0, count.value): + result.append(DownloadProvider(types[i])) + core.BNFreeDownloadProviderList(types) + return result + + def __iter__(self): + startup._init_plugins() + count = ctypes.c_ulonglong() + types = core.BNGetDownloadProviderList(count) + try: + for i in xrange(0, count.value): + yield DownloadProvider(types[i]) + finally: + core.BNFreeDownloadProviderList(types) + + def __getitem__(self, value): + startup._init_plugins() + provider = core.BNGetDownloadProviderByName(str(value)) + if provider is None: + raise KeyError("'%s' is not a valid download provider" % str(value)) + return DownloadProvider(provider) + + def __setattr__(self, name, value): + try: + type.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + +class DownloadProvider(object): + __metaclass__ = _DownloadProviderMetaclass + name = None + instance_class = None + _registered_providers = [] + + def __init__(self, handle = None): + if handle is not None: + self.handle = core.handle_of_type(handle, core.BNDownloadProvider) + self.__dict__["name"] = core.BNGetDownloadProviderName(handle) + + def register(self): + self._cb = core.BNDownloadProviderCallbacks() + self._cb.context = 0 + self._cb.createInstance = self._cb.createInstance.__class__(self._create_instance) + self.handle = core.BNRegisterDownloadProvider(self.__class__.name, self._cb) + self.__class__._registered_providers.append(self) + + def _create_instance(self, ctxt): + try: + result = self.__class__.instance_class(self) + if result is None: + return None + return ctypes.cast(core.BNNewDownloadInstanceReference(result.handle), ctypes.c_void_p).value + except: + log.log_error(traceback.format_exc()) + return None + + def create_instance(self): + result = core.BNCreateDownloadProviderInstance(self.handle) + if result is None: + return None + return DownloadInstance(self, handle = result) + + +class PythonDownloadInstance(DownloadInstance): + def __init__(self, provider): + super(PythonDownloadInstance, self).__init__(provider) + + @abc.abstractmethod + def perform_destroy_instance(self): + pass + + @abc.abstractmethod + def perform_request(self, ctxt, url): + try: + proxy_setting = Setting('download-client').get_string('https-proxy') + if proxy_setting: + opener = build_opener(ProxyHandler({'https': proxy_setting})) + install_opener(opener) + + r = urlopen(url) + total_size = int(r.headers.get('content-length', 0)) + bytes_sent = 0 + while True: + data = r.read(4096) + if not data: + break + raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) + bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) + if bytes_wrote != len(raw_bytes): + core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") + return -1 + bytes_sent = bytes_sent + bytes_wrote + continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_sent, total_size) + if continue_download is False: + core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") + return -1 + + if not bytes_sent: + core.BNSetErrorForDownloadInstance(self.handle, "Received no data!") + return -1 + + except URLError as e: + core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) + return -1 + except: + core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") + log.log_error(traceback.format_exc()) + return -1 + + return 0 + + +class PythonDownloadProvider(DownloadProvider): + name = "DefaultDownloadProvider" + instance_class = PythonDownloadInstance + + +PythonDownloadProvider().register() diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 2f293577..0cc43aca 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -32,6 +32,7 @@ class RepoPlugin(object): created by parsing the plugins.json in a plugin repository. """ def __init__(self, handle): + raise Exception("RepoPlugin temporarily disabled!") self.handle = core.handle_of_type(handle, core.BNRepoPlugin) def __del__(self): @@ -136,6 +137,7 @@ class Repository(object): ``Repository`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins. """ def __init__(self, handle): + raise Exception("Repository temporarily disabled!") self.handle = core.handle_of_type(handle, core.BNRepository) def __del__(self): @@ -199,6 +201,7 @@ class RepositoryManager(object): the plugins that are installed/unstalled enabled/disabled """ def __init__(self, handle=None): + raise Exception("RepositoryManager temporarily disabled!") self.handle = core.BNGetRepositoryManager() def __getitem__(self, repo_path): -- cgit v1.3.1 From 706039f263d79bfb15001a83e3fd87ddfc023f4a Mon Sep 17 00:00:00 2001 From: negasora Date: Fri, 22 Jun 2018 15:24:58 -0400 Subject: fix #1057 --- python/binaryview.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 0cf25e70..041974f2 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -2720,6 +2720,8 @@ class BinaryView(object): if start is None: strings = core.BNGetStrings(self.handle, count) else: + if length is None: + length = self.end - start strings = core.BNGetStringsInRange(self.handle, start, length, count) result = [] for i in xrange(0, count.value): -- cgit v1.3.1 From 32135f39bf80a08fd42dcf0fd03bd699b3b1b6db Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Tue, 26 Jun 2018 22:50:04 -0400 Subject: Add extended analysis state to core. --- binaryninjacore.h | 3 ++- python/binaryview.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/binaryninjacore.h b/binaryninjacore.h index e4fb9de2..f77a9475 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1476,7 +1476,8 @@ extern "C" { IdleState, DisassembleState, - AnalyzeState + AnalyzeState, + ExtendedAnalyzeState }; struct BNAnalysisProgress diff --git a/python/binaryview.py b/python/binaryview.py index 0cf25e70..4360502f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -156,6 +156,8 @@ class AnalysisProgress(object): return "Disassembling (%d/%d)" % (self.count, self.total) if self.state == AnalysisState.AnalyzeState: return "Analyzing (%d/%d)" % (self.count, self.total) + if self.state == AnalysisState.ExtendedAnalyzeState: + return "Extended Analysis" return "Idle" def __repr__(self): -- cgit v1.3.1 From 08409f8e134b3d93fc56e5e29670f8a8f4def890 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Tue, 26 Jun 2018 23:30:22 -0400 Subject: Add new API to query active analysis info and set analysis limits. --- binaryninjaapi.h | 23 +++++++++++++++++++++++ binaryninjacore.h | 38 ++++++++++++++++++++++++++++++++++++++ binaryview.cpp | 27 +++++++++++++++++++++++++++ function.cpp | 6 ++++++ python/binaryview.py | 43 +++++++++++++++++++++++++++++++++++++++++++ python/function.py | 7 ++++++- 6 files changed, 143 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 9c0b9bc4..f2c15fde 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1022,6 +1022,25 @@ namespace BinaryNinja void Cancel(); }; + struct ActiveAnalysisInfo + { + Ref func; + uint64_t analysisTime; + size_t updateCount; + size_t submitCount; + + ActiveAnalysisInfo(Ref f, uint64_t t, size_t uc, size_t sc) : func(f), analysisTime(t), updateCount(uc), submitCount(sc) + { + } + }; + + struct AnalysisInfo + { + BNAnalysisState state; + uint64_t analysisTime; + std::vector activeInfo; + }; + struct DataVariable { DataVariable() { } @@ -1271,6 +1290,7 @@ namespace BinaryNinja Ref AddAnalysisCompletionEvent(const std::function& callback); + AnalysisInfo GetAnalysisInfo(); BNAnalysisProgress GetAnalysisProgress(); Ref GetBackgroundAnalysisTask(); @@ -1350,6 +1370,8 @@ namespace BinaryNinja std::vector GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); + BNAnalysisParameters GetParametersForAnalysis(); + void SetParametersForAnalysis(BNAnalysisParameters params); uint64_t GetMaxFunctionSizeForAnalysis(); void SetMaxFunctionSizeForAnalysis(uint64_t size); }; @@ -2493,6 +2515,7 @@ namespace BinaryNinja bool IsFunctionTooLarge(); bool IsAnalysisSkipped(); + BNAnalysisSkipReason GetAnalysisSkipReason(); BNFunctionAnalysisSkipOverride GetAnalysisSkipOverride(); void SetAnalysisSkipOverride(BNFunctionAnalysisSkipOverride skip); }; diff --git a/binaryninjacore.h b/binaryninjacore.h index f77a9475..fda26d47 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1480,12 +1480,37 @@ extern "C" ExtendedAnalyzeState }; + struct BNActiveAnalysisInfo + { + BNFunction* func; + uint64_t analysisTime; + size_t updateCount; + size_t submitCount; + }; + + struct BNAnalysisInfo + { + BNAnalysisState state; + uint64_t analysisTime; + BNActiveAnalysisInfo* activeInfo; + size_t count; + }; + struct BNAnalysisProgress { BNAnalysisState state; size_t count, total; }; + struct BNAnalysisParameters + { + uint64_t maxAnalysisTime; + uint64_t maxFunctionSize; + uint64_t maxFunctionAnalysisTime; + size_t maxFunctionUpdateCount; + size_t maxFunctionSubmitCount; + }; + struct BNDownloadInstanceOutputCallbacks { uint64_t (*writeCallback)(uint8_t* data, uint64_t len, void* ctxt); @@ -1790,6 +1815,14 @@ extern "C" AlwaysSkipFunctionAnalysis }; + enum BNAnalysisSkipReason + { + NoSkipReason, + AlwaysSkipReason, + ExceedFunctionSizeSkipReason, + ExceedFunctionAnalysisTimeSkipReason + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size); @@ -2479,9 +2512,12 @@ extern "C" BINARYNINJACOREAPI bool BNIsFunctionTooLarge(BNFunction* func); BINARYNINJACOREAPI bool BNIsFunctionAnalysisSkipped(BNFunction* func); + BINARYNINJACOREAPI BNAnalysisSkipReason BNGetAnalysisSkipReason(BNFunction* func); BINARYNINJACOREAPI BNFunctionAnalysisSkipOverride BNGetFunctionAnalysisSkipOverride(BNFunction* func); BINARYNINJACOREAPI void BNSetFunctionAnalysisSkipOverride(BNFunction* func, BNFunctionAnalysisSkipOverride skip); + BINARYNINJACOREAPI BNAnalysisParameters BNGetParametersForAnalysis(BNBinaryView* view); + BINARYNINJACOREAPI void BNSetParametersForAnalysis(BNBinaryView* view, BNAnalysisParameters params); BINARYNINJACOREAPI uint64_t BNGetMaxFunctionSizeForAnalysis(BNBinaryView* view); BINARYNINJACOREAPI void BNSetMaxFunctionSizeForAnalysis(BNBinaryView* view, uint64_t size); @@ -2491,6 +2527,8 @@ extern "C" BINARYNINJACOREAPI void BNFreeAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); BINARYNINJACOREAPI void BNCancelAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); + BINARYNINJACOREAPI BNAnalysisInfo* BNGetAnalysisInfo(BNBinaryView* view); + BINARYNINJACOREAPI void BNFreeAnalysisInfo(BNAnalysisInfo* info); BINARYNINJACOREAPI BNAnalysisProgress BNGetAnalysisProgress(BNBinaryView* view); BINARYNINJACOREAPI BNBackgroundTask* BNGetBackgroundAnalysisTask(BNBinaryView* view); diff --git a/binaryview.cpp b/binaryview.cpp index 9aaf3595..bebfb801 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1014,6 +1014,21 @@ vector> BinaryView::GetAnalysisFunctionList() } +AnalysisInfo BinaryView::GetAnalysisInfo() +{ + AnalysisInfo result; + BNAnalysisInfo* info = BNGetAnalysisInfo(m_object); + result.state = info->state; + result.analysisTime = info->analysisTime; + result.activeInfo.reserve(info->count); + for (size_t i = 0; i < info->count; i++) + result.activeInfo.emplace_back(new Function(BNNewFunctionReference(info->activeInfo[i].func)), + info->activeInfo[i].analysisTime, info->activeInfo[i].submitCount, info->activeInfo[i].updateCount); + BNFreeAnalysisInfo(info); + return result; +} + + bool BinaryView::HasFunctions() const { return BNHasFunctions(m_object); @@ -1969,6 +1984,18 @@ uint64_t BinaryView::GetUIntMetadata(const string& key) } +BNAnalysisParameters BinaryView::GetParametersForAnalysis() +{ + return BNGetParametersForAnalysis(m_object); +} + + +void BinaryView::SetParametersForAnalysis(BNAnalysisParameters params) +{ + BNSetParametersForAnalysis(m_object, params); +} + + uint64_t BinaryView::GetMaxFunctionSizeForAnalysis() { return BNGetMaxFunctionSizeForAnalysis(m_object); diff --git a/function.cpp b/function.cpp index 835ab144..9c56c644 100644 --- a/function.cpp +++ b/function.cpp @@ -1372,6 +1372,12 @@ bool Function::IsAnalysisSkipped() } +BNAnalysisSkipReason Function::GetAnalysisSkipReason() +{ + return BNGetAnalysisSkipReason(m_object); +} + + BNFunctionAnalysisSkipOverride Function::GetAnalysisSkipOverride() { return BNGetFunctionAnalysisSkipOverride(m_object); diff --git a/python/binaryview.py b/python/binaryview.py index 4360502f..b784106e 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -145,6 +145,27 @@ class AnalysisCompletionEvent(object): core.BNCancelAnalysisCompletionEvent(self.handle) +class ActiveAnalysisInfo(object): + def __init__(self, func, analysis_time, update_count, submit_count): + self.func = func + self.analysis_time = analysis_time + self.update_count = update_count + self.submit_count = submit_count + + def __repr__(self): + return "" % (self.func, self.analysis_time, self.update_count, self.submit_count) + + +class AnalysisInfo(object): + def __init__(self, state, analysis_time, active_info): + self.state = AnalysisState(state) + self.analysis_time = analysis_time + self.active_info = active_info + + def __repr__(self): + return "" % (self.state, self.analysis_time, self.active_info) + + class AnalysisProgress(object): def __init__(self, state, count, total): self.state = state @@ -935,6 +956,20 @@ class BinaryView(object): def saved(self, value): self.file.saved = value + @property + def analysis_info(self): + """Relevant analysis information with list of functions under active analysis (read-only)""" + info_ref = core.BNGetAnalysisInfo(self.handle) + info = info_ref[0] + active_info_list = [] + for i in xrange(0, info.count): + func = function.Function(self, core.BNNewFunctionReference(info.activeInfo[i].func)) + active_info = ActiveAnalysisInfo(func, info.activeInfo[i].analysisTime, info.activeInfo[i].updateCount, info.activeInfo[i].submitCount) + active_info_list.append(active_info) + result = AnalysisInfo(info.state, info.analysisTime, active_info_list) + core.BNFreeAnalysisInfo(info_ref) + return result + @property def analysis_progress(self): """Status of current analysis (read-only)""" @@ -1026,6 +1061,14 @@ class BinaryView(object): result = core.BNGetGlobalPointerValue(self.handle) return function.RegisterValue(self.arch, result.value, confidence = result.confidence) + @property + def parameters_for_analysis(self): + return core.BNGetParametersForAnalysis(self.handle) + + @parameters_for_analysis.setter + def parameters_for_analysis(self, params): + core.BNSetParametersForAnalysis(self.handle, params) + @property def max_function_size_for_analysis(self): """Maximum size of function (sum of basic block sizes in bytes) for auto analysis""" diff --git a/python/function.py b/python/function.py index 6db44e6d..2f794f47 100644 --- a/python/function.py +++ b/python/function.py @@ -24,7 +24,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, +from enums import (AnalysisSkipReason, FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType, FunctionAnalysisSkipOverride) @@ -828,6 +828,11 @@ class Function(object): """Whether automatic analysis was skipped for this function""" return core.BNIsFunctionAnalysisSkipped(self.handle) + @property + def analysis_skip_reason(self): + """Function analysis skip reason""" + return AnalysisSkipReason(core.BNGetAnalysisSkipReason(self.handle)) + @analysis_skipped.setter def analysis_skipped(self, skip): if skip: -- cgit v1.3.1 From 8833eeb4c3b89f3ba6423b7f67a1a4277cabfc82 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Thu, 28 Jun 2018 06:58:06 -0400 Subject: Fix lifting of intrinsics in Python bindings --- binaryviewtype.cpp | 2 +- python/lowlevelil.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/binaryviewtype.cpp b/binaryviewtype.cpp index 233fdb87..762b2de7 100644 --- a/binaryviewtype.cpp +++ b/binaryviewtype.cpp @@ -29,7 +29,7 @@ BNBinaryView* BinaryViewType::CreateCallback(void* ctxt, BNBinaryView* data) BinaryViewType* type = (BinaryViewType*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref result = type->Create(view); - if (result == nullptr) + if (!result) return nullptr; return BNNewViewReference(result->GetObject()); } diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 34048704..bd1e9349 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1809,8 +1809,9 @@ class LowLevelILFunction(object): param_list = [] for param in params: param_list.append(param.index) - return self.expr(LowLevelILOperation.LLIL_INTRINSIC, len(outputs), self.add_operand_list(output_list), - self.arch.get_intrinsic_index(intrinsic), len(params), self.add_operand_list(param_list), flags = flags) + call_param = self.expr(LowLevelILOperation.LLIL_CALL_PARAM, len(params), self.add_operand_list(param_list).index) + return self.expr(LowLevelILOperation.LLIL_INTRINSIC, len(outputs), self.add_operand_list(output_list).index, + self.arch.get_intrinsic_index(intrinsic), call_param.index, flags = flags) def breakpoint(self): """ -- cgit v1.3.1 From 67209107fbfe586a39101b7135b3f041cb934abe Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Mon, 2 Jul 2018 12:35:24 -0400 Subject: downloadprovider: Fail gracefully on Ubuntu 14.04 installs, add fallback Provide a fallback so that installs with Python < 2.7.9 can still receive updates. Some manual intervention is required, but now we can provide working networking on any install that has either Python >= 2.7.9 or where a user can supply the requests[security] pip package --- python/downloadprovider.py | 176 +++++++++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 60 deletions(-) (limited to 'python') diff --git a/python/downloadprovider.py b/python/downloadprovider.py index 4756fd90..c0cecbe5 100644 --- a/python/downloadprovider.py +++ b/python/downloadprovider.py @@ -25,20 +25,11 @@ import ctypes import sys import traceback -try: - from urllib.parse import urlparse, urlencode - from urllib.request import urlopen, Request, build_opener, install_opener, ProxyHandler - from urllib.error import HTTPError, URLError -except ImportError: - from urlparse import urlparse - from urllib import urlencode - from urllib2 import urlopen, Request, build_opener, install_opener, ProxyHandler, HTTPError, URLError - # Binary Ninja Components -import _binaryninjacore as core +import binaryninja._binaryninjacore as core from binaryninja.setting import Setting -import startup -import log +from binaryninja import startup +from binaryninja import log class DownloadInstance(object): @@ -64,7 +55,7 @@ class DownloadInstance(object): def _perform_request(self, ctxt, url): try: - return self.perform_request(ctxt, url) + return self.perform_request(url) except: log.log_error(traceback.format_exc()) return -1 @@ -153,58 +144,123 @@ class DownloadProvider(object): return DownloadInstance(self, handle = result) -class PythonDownloadInstance(DownloadInstance): - def __init__(self, provider): - super(PythonDownloadInstance, self).__init__(provider) - - @abc.abstractmethod - def perform_destroy_instance(self): - pass - - @abc.abstractmethod - def perform_request(self, ctxt, url): - try: - proxy_setting = Setting('download-client').get_string('https-proxy') - if proxy_setting: - opener = build_opener(ProxyHandler({'https': proxy_setting})) - install_opener(opener) - - r = urlopen(url) - total_size = int(r.headers.get('content-length', 0)) - bytes_sent = 0 - while True: - data = r.read(4096) - if not data: - break - raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) - bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) - if bytes_wrote != len(raw_bytes): - core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") - return -1 - bytes_sent = bytes_sent + bytes_wrote - continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_sent, total_size) - if continue_download is False: - core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") +if sys.version_info >= (2, 7, 9): + try: + from urllib.request import urlopen, build_opener, install_opener, ProxyHandler + from urllib.error import URLError + except ImportError: + from urllib2 import urlopen, build_opener, install_opener, ProxyHandler, URLError + + class PythonDownloadInstance(DownloadInstance): + def __init__(self, provider): + super(PythonDownloadInstance, self).__init__(provider) + + @abc.abstractmethod + def perform_destroy_instance(self): + pass + + @abc.abstractmethod + def perform_request(self, url): + try: + proxy_setting = Setting('download-client').get_string('https-proxy') + if proxy_setting: + opener = build_opener(ProxyHandler({'https': proxy_setting})) + install_opener(opener) + + r = urlopen(url.decode("charmap")) + total_size = int(r.headers.get('content-length', 0)) + bytes_sent = 0 + while True: + data = r.read(4096) + if not data: + break + raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) + bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) + if bytes_wrote != len(raw_bytes): + core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") + return -1 + bytes_sent = bytes_sent + bytes_wrote + continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_sent, total_size) + if continue_download is False: + core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") + return -1 + + if not bytes_sent: + core.BNSetErrorForDownloadInstance(self.handle, "Received no data!") return -1 - if not bytes_sent: - core.BNSetErrorForDownloadInstance(self.handle, "Received no data!") + except URLError as e: + core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) + return -1 + except: + core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") + log.log_error(traceback.format_exc()) return -1 - except URLError as e: - core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) - return -1 - except: - core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") - log.log_error(traceback.format_exc()) - return -1 - - return 0 + return 0 + + class PythonDownloadProvider(DownloadProvider): + name = "DefaultDownloadProvider" + instance_class = PythonDownloadInstance + + PythonDownloadProvider().register() +else: + try: + import requests + from requests import pyopenssl + class PythonDownloadInstance(DownloadInstance): + def __init__(self, provider): + super(PythonDownloadInstance, self).__init__(provider) + + @abc.abstractmethod + def perform_destroy_instance(self): + pass + + @abc.abstractmethod + def perform_request(self, url): + try: + proxy_setting = Setting('download-client').get_string('https-proxy') + if proxy_setting: + proxies = {"https": proxy_setting} + else: + proxies = None + + r = requests.get(url.decode("charmap"), proxies=proxies) + if not r.ok: + core.BNSetErrorForDownloadInstance(self.handle, "Received error from server") + return -1 + data = r.content + if len(data) == 0: + core.BNSetErrorForDownloadInstance(self.handle, "No data received from server!") + return -1 + raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) + bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) + if bytes_wrote != len(raw_bytes): + core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") + return -1 + continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_wrote, bytes_wrote) + if continue_download is False: + core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") + return -1 + except requests.RequestException as e: + core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) + return -1 + except: + core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") + log.log_error(traceback.format_exc()) + return -1 + return 0 -class PythonDownloadProvider(DownloadProvider): - name = "DefaultDownloadProvider" - instance_class = PythonDownloadInstance + class PythonDownloadProvider(DownloadProvider): + name = "DefaultDownloadProvider" + instance_class = PythonDownloadInstance + PythonDownloadProvider().register() + except ImportError: + log.log_error("On this version of Python, the pip requests[security] package is required for network connectivity!") + log.log_error("On an Ubuntu 14.04 install, the following three commands are sufficient to enable networking for the current user:") + log.log_error(" sudo apt install python-pip") + log.log_error(" python -m pip install pip --upgrade --user") + log.log_error(" python -m pip install requests[security] --upgrade --user") -PythonDownloadProvider().register() -- cgit v1.3.1 From bc8f53abc3885824ae1eaca79c95ce83a3a3a643 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Mon, 2 Jul 2018 13:55:27 -0400 Subject: python: avoid auto-generating docs for live content --- python/update.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'python') diff --git a/python/update.py b/python/update.py index a89c9348..1eb8ea61 100644 --- a/python/update.py +++ b/python/update.py @@ -116,11 +116,6 @@ class UpdateChannel(object): self.description = desc self.latest_version_num = ver - @property - def list(self): - """Allow tab completion to discover metaclass list property""" - pass - @property def versions(self): """List of versions (read-only)""" -- cgit v1.3.1 From bbc3116e82e8d92084a0e667e6f5222fc1455999 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Fri, 6 Jul 2018 11:10:04 -0400 Subject: python: fix BasicBlock iteration for invalid instructions --- python/basicblock.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index c55e15f0..a79b53ad 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -312,6 +312,8 @@ class BasicBlock(object): inst_info = self.arch.get_instruction_info(data, idx) inst_text = self.arch.get_instruction_text(data, idx) + if inst_info is None: + break yield inst_text idx += inst_info.length -- cgit v1.3.1 From 4f1a7824357ab58d868dbd675af9b152fc3694e9 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Fri, 6 Jul 2018 21:15:02 -0400 Subject: Python: More useful error when loading too-old Python on Windows --- python/downloadprovider.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'python') diff --git a/python/downloadprovider.py b/python/downloadprovider.py index c0cecbe5..d34ca358 100644 --- a/python/downloadprovider.py +++ b/python/downloadprovider.py @@ -258,9 +258,12 @@ else: PythonDownloadProvider().register() except ImportError: - log.log_error("On this version of Python, the pip requests[security] package is required for network connectivity!") - log.log_error("On an Ubuntu 14.04 install, the following three commands are sufficient to enable networking for the current user:") - log.log_error(" sudo apt install python-pip") - log.log_error(" python -m pip install pip --upgrade --user") - log.log_error(" python -m pip install requests[security] --upgrade --user") + if sys.platform == "win32": + log.log_error("Provided Python version is too old! Only Python 2.7.10 and above are known to work on Windows!") + else: + log.log_error("On Python versions below 2.7.9, the pip requests[security] package is required for network connectivity!") + log.log_error("On an Ubuntu 14.04 install, the following three commands are sufficient to enable networking for the current user:") + log.log_error(" sudo apt install python-pip") + log.log_error(" python -m pip install pip --upgrade --user") + log.log_error(" python -m pip install requests[security] --upgrade --user") -- cgit v1.3.1