-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[5895] added code to raise error in sleep if invalid value #5907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -90,8 +90,22 @@ mod decl { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(not(unix))] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[pyfunction] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn sleep(dur: Duration) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::thread::sleep(dur); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn sleep(secs: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try to get as float first, if that fails try as integer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let secs = if let Ok(float_val) = f64::try_from_object(vm, secs.clone()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| float_val | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if let Ok(int_val) = i64::try_from_object(vm, secs) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int_val as f64 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(vm.new_type_error("sleep() argument must be a number")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !secs.is_finite() || secs < 0.0 || secs > u64::MAX as f64 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(vm.new_value_error("sleep length must be a non-negative finite number")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
DominicPrince2003 marked this conversation as resolved.
Outdated
Comment on lines
+94
to
+104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This validation logic is duplicated in the For example: fn get_sleep_secs(secs_obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<f64> {
// Try to get as float first, if that fails try as integer
let secs = if let Ok(float_val) = f64::try_from_object(vm, secs_obj.clone()) {
float_val
} else if let Ok(int_val) = i64::try_from_object(vm, secs_obj) {
int_val as f64
} else {
return Err(vm.new_type_error("sleep() argument must be a number"));
};
if !secs.is_finite() || secs < 0.0 || secs > u64::MAX as f64 {
return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
}
Ok(secs)
} |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let duration = Duration::from_secs_f64(secs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::thread::sleep(duration); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+93
to
109
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix potential precision issue with u64::MAX conversion. The validation logic has a potential issue with floating-point precision. When Consider this alternative approach that handles the precision issue: - if !secs.is_finite() || secs < 0.0 || secs > u64::MAX as f64 {
- return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
- }
+ if !secs.is_finite() {
+ return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
+ }
+ if secs < 0.0 {
+ return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
+ }
+ // Check for values that would overflow when converted to Duration
+ if secs > Duration::MAX.as_secs_f64() {
+ return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
+ }This approach uses 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents💡 Verification agent 🧩 Analysis chainVerify error message consistency with CPython. Ensure that the error messages match CPython's behavior for better compatibility. The current generic message might not align with Python's standard library. Also applies to: 708-721 🏁 Script executed: #!/bin/bash
# Check CPython's error messages for time.sleep() with invalid arguments
python3 -c "
import time
try:
time.sleep(-1)
except ValueError as e:
print('Negative value error:', e)
try:
time.sleep('invalid')
except TypeError as e:
print('Type error:', e)
try:
time.sleep(float('inf'))
except ValueError as e:
print('Infinity error:', e)
try:
time.sleep(float('nan'))
except ValueError as e:
print('NaN error:', e)
"Length of output: 669 🏁 Script executed: #!/bin/bash
# Enhanced check of CPython’s error messages for time.sleep() with various invalid arguments
python3 - << 'PYCODE'
import time
tests = [
(-1, "negative"),
("invalid","string"),
(float('inf'), "infinite"),
(float('nan'), "nan")
]
for val, label in tests:
try:
time.sleep(val)
except Exception as e:
print(f"{label} -> {type(e).__name__}: {e}")
PYCODELength of output: 264 Match CPython’s time.sleep error messages The generic checks in
Apply the same adjustments in the secondary implementation at lines 708–721. Locations to update:
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(not(target_os = "wasi"))] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -527,7 +541,7 @@ mod platform { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PyObject, PyRef, PyResult, TryFromBorrowedObject, VirtualMachine, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| builtins::{PyNamespace, PyStrRef}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| convert::IntoPyException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| convert::{IntoPyException,TryFromObject}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use nix::{sys::time::TimeSpec, time::ClockId}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::time::Duration; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -691,9 +705,20 @@ mod platform { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[pyfunction] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn sleep(dur: Duration, vm: &VirtualMachine) -> PyResult<()> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn sleep(secs: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // this is basically std::thread::sleep, but that catches interrupts and we don't want to; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try to get as float first, if that fails try as integer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let secs = if let Ok(float_val) = f64::try_from_object(vm, secs.clone()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| float_val | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if let Ok(int_val) = i64::try_from_object(vm, secs) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int_val as f64 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(vm.new_type_error("sleep() argument must be a number")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !secs.is_finite() || secs < 0.0 || secs > u64::MAX as f64 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(vm.new_value_error("sleep length must be a non-negative finite number")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
DominicPrince2003 marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let dur = Duration::from_secs_f64(secs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+708
to
+721
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix potential precision issue with u64::MAX conversion (Unix implementation). Same precision issue exists in the Unix implementation as in the non-Unix version. Apply the same fix as suggested for the non-Unix implementation: - if !secs.is_finite() || secs < 0.0 || secs > u64::MAX as f64 {
- return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
- }
+ if !secs.is_finite() {
+ return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
+ }
+ if secs < 0.0 {
+ return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
+ }
+ // Check for values that would overflow when converted to Duration
+ if secs > Duration::MAX.as_secs_f64() {
+ return Err(vm.new_value_error("sleep length must be a non-negative finite number"));
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let ts = TimeSpec::from(dur); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let res = unsafe { libc::nanosleep(ts.as_ref(), std::ptr::null_mut()) }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let interrupted = res == -1 && nix::Error::last_raw() == libc::EINTR; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since
Lib/test/test_time.pyis originated from CPython, we usually don't directly edit this file.We usually add our original test under
extra_testslikeextra_tests/snippets/stdlib_time.py.If you also want to contribute to CPython, you can submit a similar patch to CPyhton project: https://github.com/python/cpython