From 57f042a802e324cc36bd976b531ddf57f0ea609e Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Sat, 7 Feb 2026 06:22:25 -0700 Subject: [PATCH] Fix exception handling for functions_create and data_create - Change from 'except Exception' to bare 'except' to catch Java exceptions from Ghidra that don't inherit from Python Exception - Use sys.exc_info() to safely extract error messages when str(e) might fail on certain Java exception types - Add null checks after getAddress() since it can return None instead of throwing for invalid addresses - Add last-resort response handling to prevent silent connection drops when exception handling itself fails These endpoints now return proper JSON error responses instead of causing "Empty reply from server" errors. --- docker/MCGhidraServer.py | 58 +++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/docker/MCGhidraServer.py b/docker/MCGhidraServer.py index 47f74da..bc5c322 100644 --- a/docker/MCGhidraServer.py +++ b/docker/MCGhidraServer.py @@ -412,14 +412,30 @@ class MCGhidraHandler(HttpHandler): "success": False, "error": {"code": "NOT_FOUND", "message": "Endpoint not found: %s %s" % (method, path)} }) - except Exception as e: + except: + # Catch ALL exceptions including Java exceptions + import sys + exc_info = sys.exc_info() + try: + # Try to get a string representation safely + if exc_info[1] is not None: + msg = str(exc_info[1]) + else: + msg = str(exc_info[0]) + except: + msg = "Unknown exception" try: self._send_response(exchange, 500, { "success": False, - "error": {"code": "INTERNAL_ERROR", "message": str(e)} + "error": {"code": "INTERNAL_ERROR", "message": msg} }) except: - pass + # Last resort - at least don't crash silently + try: + exchange.sendResponseHeaders(500, 0) + exchange.getResponseBody().close() + except: + pass def _send_response(self, exchange, code, data): response_bytes = json.dumps(data, indent=2).encode('utf-8') @@ -992,6 +1008,9 @@ class MCGhidraHandler(HttpHandler): except: return {"success": False, "error": {"code": "INVALID_ADDRESS", "message": "Invalid address: %s" % addr_str}} + if addr is None: + return {"success": False, "error": {"code": "INVALID_ADDRESS", "message": "Could not parse address: %s" % addr_str}} + result_holder = [None] def do_create(): @@ -1009,8 +1028,14 @@ class MCGhidraHandler(HttpHandler): "message": "Function created successfully", }}, 201) return {"success": False, "error": {"code": "CREATE_FAILED", "message": "Failed to create function at %s" % addr_str}} - except Exception as e: - return {"success": False, "error": {"code": "CREATE_ERROR", "message": str(e)}} + except: + import sys + exc = sys.exc_info()[1] + try: + msg = str(exc) + except: + msg = "Failed to create function" + return {"success": False, "error": {"code": "CREATE_ERROR", "message": msg}} # -- Signature -- @@ -1156,6 +1181,9 @@ class MCGhidraHandler(HttpHandler): except: return {"success": False, "error": {"code": "INVALID_ADDRESS", "message": "Invalid address: %s" % addr_str}} + if addr is None: + return {"success": False, "error": {"code": "INVALID_ADDRESS", "message": "Could not parse address: %s" % addr_str}} + # Label creation (newName field) new_name = body.get("newName") if new_name: @@ -1164,8 +1192,14 @@ class MCGhidraHandler(HttpHandler): try: with_transaction(self.program, "Create label", do_label) return {"success": True, "result": {"address": addr_str, "name": new_name, "message": "Label created"}} - except Exception as e: - return {"success": False, "error": {"code": "LABEL_ERROR", "message": str(e)}} + except: + import sys + exc = sys.exc_info()[1] + try: + msg = str(exc) + except: + msg = "Failed to create label" + return {"success": False, "error": {"code": "LABEL_ERROR", "message": msg}} # Data creation (type field) type_name = body.get("type") @@ -1187,8 +1221,14 @@ class MCGhidraHandler(HttpHandler): try: with_transaction(self.program, "Create data", do_create_data) return ({"success": True, "result": {"address": addr_str, "type": type_name, "message": "Data created"}}, 201) - except Exception as e: - return {"success": False, "error": {"code": "DATA_ERROR", "message": str(e)}} + except: + import sys + exc = sys.exc_info()[1] + try: + msg = str(exc) + except: + msg = "Failed to create data" + return {"success": False, "error": {"code": "DATA_ERROR", "message": msg}} def handle_data_delete(self, exchange): if not self.program: