Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions common/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2028,7 +2028,12 @@ def inhibitSuspend(app_id = sys.argv[0],
try:
if not toplevel_xid:
toplevel_xid = 0
except IndexError:
# Ensure toplevel_xid fits in UInt32 range (0 to 4294967295)
# If it's too large, use 0 as fallback since window ID is not critical for inhibit
elif toplevel_xid > 0xFFFFFFFF: # 4294967295
logger.debug(f'Window ID {toplevel_xid} exceeds UInt32 range, using 0 as fallback')
toplevel_xid = 0
except (IndexError, TypeError, ValueError):
toplevel_xid = 0

for dbus_props in INHIBIT_DBUS:
Expand All @@ -2042,7 +2047,14 @@ def inhibitSuspend(app_id = sys.argv[0],
bus = dbus.SessionBus() # This code may hang forever (if BiT is run as root via cron job and no user is logged in). See #1592
interface = bus.get_object(dbus_props['service'], dbus_props['objectPath'])
proxy = interface.get_dbus_method(dbus_props['methodSet'], dbus_props['interface'])
cookie = proxy(*[(app_id, dbus.UInt32(toplevel_xid), reason, dbus.UInt32(flags))[i] for i in dbus_props['arguments']])
# Handle potential UInt32 overflow by wrapping the conversion in try-catch
try:
args_tuple = (app_id, dbus.UInt32(toplevel_xid), reason, dbus.UInt32(flags))
cookie = proxy(*[args_tuple[i] for i in dbus_props['arguments']])
except OverflowError as e:
logger.debug(f'UInt32 overflow with toplevel_xid={toplevel_xid}, using 0 as fallback: {e}')
args_tuple = (app_id, dbus.UInt32(0), reason, dbus.UInt32(flags))
cookie = proxy(*[args_tuple[i] for i in dbus_props['arguments']])
logger.debug('Inhibit Suspend started. Reason: {}'.format(reason))
return (cookie, bus, dbus_props)
except dbus.exceptions.DBusException:
Expand Down
55 changes: 55 additions & 0 deletions test_restore_scenario.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
"""
Test script to simulate the exact restore scenario that was failing.
"""
import sys
import os

# Add the common directory to Python path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'common'))

class MockConfig:
"""Mock config object to simulate the restore dialog scenario."""
def __init__(self, xWindowId):
self.xWindowId = xWindowId
self.inhibitCookie = None

def test_restore_scenario():
"""Test the exact scenario from restoredialog.py line 82."""
try:
import tools

# Simulate the problematic config with the X Window ID from the error
config = MockConfig(xWindowId=527453920)

print(f"Simulating restore dialog with X Window ID: {config.xWindowId}")

# This is the exact line that was failing in restoredialog.py:82
config.inhibitCookie = tools.inhibitSuspend(
toplevel_xid=config.xWindowId,
reason='restoring'
)

if config.inhibitCookie:
print("✓ Restore dialog inhibitSuspend call succeeded!")
cookie, bus, dbus_props = config.inhibitCookie
print(f" Cookie: {cookie}")

# Clean up
tools.unInhibitSuspend(cookie, bus, dbus_props)
print("✓ Cleanup successful!")
else:
print("⚠ inhibitSuspend returned None (expected if no dbus available)")

print("\n✓ Restore scenario test completed successfully!")
return True

except Exception as e:
print(f"✗ Restore scenario test failed: {e}")
import traceback
traceback.print_exc()
return False

if __name__ == "__main__":
success = test_restore_scenario()
sys.exit(0 if success else 1)
59 changes: 59 additions & 0 deletions test_uint32_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
"""
Test script to verify the UInt32 overflow fix in inhibitSuspend function.
"""
import sys
import os

# Add the common directory to Python path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'common'))

try:
import tools

# Test with the problematic value from the error report
problematic_xid = 527453920
print(f"Testing with X Window ID: {problematic_xid}")

# This should not crash anymore
result = tools.inhibitSuspend(
app_id='test_backintime',
toplevel_xid=problematic_xid,
reason='testing fix'
)

if result:
print("✓ inhibitSuspend succeeded!")
cookie, bus, dbus_props = result
print(f" Cookie: {cookie}")

# Clean up
tools.unInhibitSuspend(cookie, bus, dbus_props)
print("✓ unInhibitSuspend succeeded!")
else:
print("⚠ inhibitSuspend returned None (expected if no dbus available)")

# Test with an even larger value that definitely exceeds UInt32
large_xid = 5000000000 # > 4294967295
print(f"\nTesting with large X Window ID: {large_xid}")

result = tools.inhibitSuspend(
app_id='test_backintime',
toplevel_xid=large_xid,
reason='testing large value'
)

if result:
print("✓ inhibitSuspend with large value succeeded!")
cookie, bus, dbus_props = result
tools.unInhibitSuspend(cookie, bus, dbus_props)
else:
print("⚠ inhibitSuspend with large value returned None")

print("\n✓ All tests completed without crashes!")

except Exception as e:
print(f"✗ Test failed with error: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
34 changes: 34 additions & 0 deletions uint32_overflow_fix.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
diff --git a/common/tools.py b/common/tools.py
index 7ceb7aca..7c110f09 100644
--- a/common/tools.py
+++ b/common/tools.py
@@ -2028,7 +2028,12 @@ def inhibitSuspend(app_id = sys.argv[0],
try:
if not toplevel_xid:
toplevel_xid = 0
- except IndexError:
+ # Ensure toplevel_xid fits in UInt32 range (0 to 4294967295)
+ # If it's too large, use 0 as fallback since window ID is not critical for inhibit
+ elif toplevel_xid > 0xFFFFFFFF: # 4294967295
+ logger.debug(f'Window ID {toplevel_xid} exceeds UInt32 range, using 0 as fallback')
+ toplevel_xid = 0
+ except (IndexError, TypeError, ValueError):
toplevel_xid = 0

for dbus_props in INHIBIT_DBUS:
@@ -2042,7 +2047,14 @@ def inhibitSuspend(app_id = sys.argv[0],
bus = dbus.SessionBus() # This code may hang forever (if BiT is run as root via cron job and no user is logged in). See #1592
interface = bus.get_object(dbus_props['service'], dbus_props['objectPath'])
proxy = interface.get_dbus_method(dbus_props['methodSet'], dbus_props['interface'])
- cookie = proxy(*[(app_id, dbus.UInt32(toplevel_xid), reason, dbus.UInt32(flags))[i] for i in dbus_props['arguments']])
+ # Handle potential UInt32 overflow by wrapping the conversion in try-catch
+ try:
+ args_tuple = (app_id, dbus.UInt32(toplevel_xid), reason, dbus.UInt32(flags))
+ cookie = proxy(*[args_tuple[i] for i in dbus_props['arguments']])
+ except OverflowError as e:
+ logger.debug(f'UInt32 overflow with toplevel_xid={toplevel_xid}, using 0 as fallback: {e}')
+ args_tuple = (app_id, dbus.UInt32(0), reason, dbus.UInt32(flags))
+ cookie = proxy(*[args_tuple[i] for i in dbus_props['arguments']])
logger.debug('Inhibit Suspend started. Reason: {}'.format(reason))
return (cookie, bus, dbus_props)
except dbus.exceptions.DBusException: