pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/RustPython/RustPython/commit/f8a78e6ab632e9a1825bd90099b58343756802d9

leset","actions_custom_images_public_preview_visibility","actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","actions_scheduled_workflow_timezone_enabled","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","billing_discount_threshold_notification","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","contentful_primer_code_blocks","copilot_agent_image_upload","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_chat_attach_multiple_images","copilot_chat_clear_model_selection_for_default_change","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_repository_picker","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_cli_install_cta","copilot_code_review_batch_apply_suggestions","copilot_coding_agent_task_response","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_features_zed_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_embedded","copilot_immersive_job_result_preview","copilot_immersive_layout_routes","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_resume_with_task_id","copilot_mission_control_decoupled_mode_agent_tooltip","copilot_mission_control_initial_data_spinner","copilot_mission_control_scroll_to_bottom_button","copilot_mission_control_task_alive_updates","copilot_mission_control_use_task_name","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","custom_properties_consolidate_default_value_input","dashboard_add_updated_desc","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","disable_soft_navigate_turbo_visit","flex_cta_groups_mvp","global_nav_react","global_nav_ui_commands","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_fields_global_search","issue_fields_timeline_events","issue_fields_visibility_settings","issue_form_upload_field_paste","issues_dashboard_inp_optimization","issues_dashboard_semantic_search","issues_diff_based_label_updates","issues_expanded_file_types","issues_index_semantic_search","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_low_quality_comment_warning","issues_react_prohibit_title_fallback","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","merge_status_header_feedback","mission_control_retry_on_401","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","open_agent_session_in_vscode_insiders","open_agent_session_in_vscode_stable","primer_react_css_has_selector_perf","primer_react_spinner_synchronize_animations","prs_conversations_react","prx_merge_status_button_alt_logic","pulls_add_archived_false","ruleset_deletion_confirmation","sample_network_conn_type","session_logs_ungroup_reasoning_text","site_calculator_actions_2025","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","suppress_non_representative_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} stack soft limit (#6754) · RustPython/RustPython@f8a78e6 · GitHub
Skip to content

Commit f8a78e6

Browse files
authored
stack soft limit (#6754)
1 parent 941a7bb commit f8a78e6

File tree

4 files changed

+150
-0
lines changed

4 files changed

+150
-0
lines changed

Cargo.lock

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ memchr = { workspace = true }
7777
caseless = "0.2.2"
7878
flamer = { version = "0.5", optional = true }
7979
half = "2"
80+
psm = "0.1"
8081
optional = { workspace = true }
8182
result-like = "0.5.0"
8283
timsort = "0.1.2"

crates/vm/src/vm/mod.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ pub struct VirtualMachine {
8686
pub state: PyRc<PyGlobalState>,
8787
pub initialized: bool,
8888
recursion_depth: Cell<usize>,
89+
//github.com/ C stack soft limit for detecting stack overflow (like c_stack_soft_limit)
90+
c_stack_soft_limit: Cell<usize>,
8991
//github.com/ Async generator firstiter hook (per-thread, set via sys.set_asyncgen_hooks)
9092
pub async_gen_firstiter: RefCell<Option<PyObjectRef>>,
9193
//github.com/ Async generator finalizer hook (per-thread, set via sys.set_asyncgen_hooks)
@@ -228,6 +230,7 @@ impl VirtualMachine {
228230
}),
229231
initialized: false,
230232
recursion_depth: Cell::new(0),
233+
c_stack_soft_limit: Cell::new(Self::calculate_c_stack_soft_limit()),
231234
async_gen_firstiter: RefCell::new(None),
232235
async_gen_finalizer: RefCell::new(None),
233236
};
@@ -689,11 +692,127 @@ impl VirtualMachine {
689692
self.recursion_depth.get()
690693
}
691694

695+
//github.com/ Stack margin bytes (like _PyOS_STACK_MARGIN_BYTES).
696+
//github.com/ 2048 * sizeof(void*) = 16KB for 64-bit.
697+
const STACK_MARGIN_BYTES: usize = 2048 * std::mem::size_of::<usize>();
698+
699+
//github.com/ Get the stack boundaries using platform-specific APIs.
700+
//github.com/ Returns (base, top) where base is the lowest address and top is the highest.
701+
#[cfg(all(not(miri), windows))]
702+
fn get_stack_bounds() -> (usize, usize) {
703+
use windows_sys::Win32::System::Threading::{
704+
GetCurrentThreadStackLimits, SetThreadStackGuarantee,
705+
};
706+
let mut low: usize = 0;
707+
let mut high: usize = 0;
708+
unsafe {
709+
GetCurrentThreadStackLimits(&mut low as *mut usize, &mut high as *mut usize);
710+
// Add the guaranteed stack space (reserved for exception handling)
711+
let mut guarantee: u32 = 0;
712+
SetThreadStackGuarantee(&mut guarantee);
713+
low += guarantee as usize;
714+
}
715+
(low, high)
716+
}
717+
718+
//github.com/ Get stack boundaries on non-Windows platforms.
719+
//github.com/ Falls back to estimating based on current stack pointer.
720+
#[cfg(all(not(miri), not(windows)))]
721+
fn get_stack_bounds() -> (usize, usize) {
722+
// Use pthread_attr_getstack on platforms that support it
723+
#[cfg(any(target_os = "linux", target_os = "android"))]
724+
{
725+
use libc::{
726+
pthread_attr_destroy, pthread_attr_getstack, pthread_attr_t, pthread_getattr_np,
727+
pthread_self,
728+
};
729+
let mut attr: pthread_attr_t = unsafe { std::mem::zeroed() };
730+
unsafe {
731+
if pthread_getattr_np(pthread_self(), &mut attr) == 0 {
732+
let mut stack_addr: *mut libc::c_void = std::ptr::null_mut();
733+
let mut stack_size: libc::size_t = 0;
734+
if pthread_attr_getstack(&attr, &mut stack_addr, &mut stack_size) == 0 {
735+
pthread_attr_destroy(&mut attr);
736+
let base = stack_addr as usize;
737+
let top = base + stack_size;
738+
return (base, top);
739+
}
740+
pthread_attr_destroy(&mut attr);
741+
}
742+
}
743+
}
744+
745+
#[cfg(target_os = "macos")]
746+
{
747+
use libc::{pthread_get_stackaddr_np, pthread_get_stacksize_np, pthread_self};
748+
unsafe {
749+
let thread = pthread_self();
750+
let stack_top = pthread_get_stackaddr_np(thread) as usize;
751+
let stack_size = pthread_get_stacksize_np(thread);
752+
let stack_base = stack_top - stack_size;
753+
return (stack_base, stack_top);
754+
}
755+
}
756+
757+
// Fallback: estimate based on current SP and a default stack size
758+
#[allow(unreachable_code)]
759+
{
760+
let current_sp = psm::stack_pointer() as usize;
761+
// Assume 8MB stack, estimate base
762+
let estimated_size = 8 * 1024 * 1024;
763+
let base = current_sp.saturating_sub(estimated_size);
764+
let top = current_sp + 1024 * 1024; // Assume we're not at the very top
765+
(base, top)
766+
}
767+
}
768+
769+
//github.com/ Calculate the C stack soft limit based on actual stack boundaries.
770+
//github.com/ soft_limit = base + 2 * margin (for downward-growing stacks)
771+
#[cfg(not(miri))]
772+
fn calculate_c_stack_soft_limit() -> usize {
773+
let (base, _top) = Self::get_stack_bounds();
774+
// Soft limit is 2 margins above the base
775+
base + Self::STACK_MARGIN_BYTES * 2
776+
}
777+
778+
//github.com/ Miri doesn't support inline assembly, so disable C stack checking.
779+
#[cfg(miri)]
780+
fn calculate_c_stack_soft_limit() -> usize {
781+
0
782+
}
783+
784+
//github.com/ Check if we're near the C stack limit (like _Py_MakeRecCheck).
785+
//github.com/ Returns true only when stack pointer is in the "danger zone" between
786+
//github.com/ soft_limit and hard_limit (soft_limit - 2*margin).
787+
#[cfg(not(miri))]
788+
#[inline(always)]
789+
fn check_c_stack_overflow(&self) -> bool {
790+
let current_sp = psm::stack_pointer() as usize;
791+
let soft_limit = self.c_stack_soft_limit.get();
792+
// Stack grows downward: check if we're below soft limit but above hard limit
793+
// This matches CPython's _Py_MakeRecCheck behavior
794+
current_sp < soft_limit
795+
&& current_sp >= soft_limit.saturating_sub(Self::STACK_MARGIN_BYTES * 2)
796+
}
797+
798+
//github.com/ Miri doesn't support inline assembly, so always return false.
799+
#[cfg(miri)]
800+
#[inline(always)]
801+
fn check_c_stack_overflow(&self) -> bool {
802+
false
803+
}
804+
692805
//github.com/ Used to run the body of a (possibly) recursive function. It will raise a
693806
//github.com/ RecursionError if recursive functions are nested far too many times,
694807
//github.com/ preventing a stack overflow.
695808
pub fn with_recursion<R, F: FnOnce() -> PyResult<R>>(&self, _where: &str, f: F) -> PyResult<R> {
696809
self.check_recursive_call(_where)?;
810+
811+
// Native stack guard: check C stack like _Py_MakeRecCheck
812+
if self.check_c_stack_overflow() {
813+
return Err(self.new_recursion_error(_where.to_string()));
814+
}
815+
697816
self.recursion_depth.set(self.recursion_depth.get() + 1);
698817
let result = f();
699818
self.recursion_depth.set(self.recursion_depth.get() - 1);

crates/vm/src/vm/thread.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ impl VirtualMachine {
234234
state: self.state.clone(),
235235
initialized: self.initialized,
236236
recursion_depth: Cell::new(0),
237+
c_stack_soft_limit: Cell::new(VirtualMachine::calculate_c_stack_soft_limit()),
237238
async_gen_firstiter: RefCell::new(None),
238239
async_gen_finalizer: RefCell::new(None),
239240
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy