mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 03:22:43 +00:00 
			
		
		
		
	LibWeb: Make frames nesting-aware and disallow deep nesting
A Frame now knows about its nesting-level. The FrameLoader checks whether the recursion level of the current frame allows it to be displayed and if not doesn't even load the requested resource. The nesting-check is done on a per-URL-basis, so there can be many many nested Frames as long as they have different URLs. If there are however Frames with the same URL nested inside each other we only allow this to happen 3 times. This mitigates infinetely recursing <iframe>s in an HTML-document crashing the browser with an OOM.
This commit is contained in:
		
							parent
							
								
									9e49895bbf
								
							
						
					
					
						commit
						1b6824d296
					
				
					 4 changed files with 27 additions and 1 deletions
				
			
		|  | @ -26,8 +26,11 @@ void FrameHostElement::inserted() | |||
|     HTMLElement::inserted(); | ||||
|     if (!is_connected()) | ||||
|         return; | ||||
|     if (auto* frame = document().frame()) | ||||
|     if (auto* frame = document().frame()) { | ||||
|         m_content_frame = Frame::create_subframe(*this, frame->main_frame()); | ||||
|         m_content_frame->set_frame_nesting_levels(frame->frame_nesting_levels()); | ||||
|         m_content_frame->register_frame_nesting(document().url()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| Origin FrameHostElement::content_origin() const | ||||
|  |  | |||
|  | @ -136,6 +136,11 @@ bool FrameLoader::load(const LoadRequest& request, Type type) | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if (!m_frame.is_frame_nesting_allowed(request.url())) { | ||||
|         dbgln("No further recursion is allowed for the frame, abort load!"); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     auto& url = request.url(); | ||||
| 
 | ||||
|     set_resource(ResourceLoader::the().load_resource(Resource::Type::Generic, request)); | ||||
|  |  | |||
|  | @ -286,4 +286,14 @@ void Frame::unregister_viewport_client(ViewportClient& client) | |||
|     VERIFY(was_removed); | ||||
| } | ||||
| 
 | ||||
| void Frame::register_frame_nesting(URL const& url) | ||||
| { | ||||
|     m_frame_nesting_levels.ensure(url)++; | ||||
| } | ||||
| 
 | ||||
| bool Frame::is_frame_nesting_allowed(URL const& url) const | ||||
| { | ||||
|     return m_frame_nesting_levels.get(url).value_or(0) < 3; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -81,6 +81,12 @@ public: | |||
| 
 | ||||
|     void did_edit(Badge<EditEventHandler>); | ||||
| 
 | ||||
|     void register_frame_nesting(URL const&); | ||||
|     bool is_frame_nesting_allowed(URL const&) const; | ||||
| 
 | ||||
|     void set_frame_nesting_levels(const HashMap<URL, size_t> frame_nesting_levels) { m_frame_nesting_levels = move(frame_nesting_levels); }; | ||||
|     HashMap<URL, size_t> const& frame_nesting_levels() const { return m_frame_nesting_levels; } | ||||
| 
 | ||||
| private: | ||||
|     explicit Frame(DOM::Element& host_element, Frame& main_frame); | ||||
|     explicit Frame(Page&); | ||||
|  | @ -105,6 +111,8 @@ private: | |||
|     bool m_cursor_blink_state { false }; | ||||
| 
 | ||||
|     HashTable<ViewportClient*> m_viewport_clients; | ||||
| 
 | ||||
|     HashMap<URL, size_t> m_frame_nesting_levels; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tobias Christiansen
						Tobias Christiansen