File tree Expand file tree Collapse file tree 5 files changed +34
-4
lines changed Expand file tree Collapse file tree 5 files changed +34
-4
lines changed Original file line number Diff line number Diff line change @@ -11,6 +11,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
1111-  v2.8.3(Unreleased)
1212  -  Bumped cryptography dependency from <39.0.0 to <41.0.0
1313  -  Fixed a bug where the permission of the file downloaded via GET command is changed
14+   -  Fixed a bug where expired OCSP response cache caused infinite recursion during cache loading
1415
1516-  v2.8.2(November 18,2022)
1617
Original file line number Diff line number Diff line change @@ -58,6 +58,8 @@ def __init__(
5858        self ._cache : dict [K , CacheEntry [V ]] =  {}
5959        self ._lock  =  Lock ()
6060        self ._reset_telemetry ()
61+         # aliasing _getitem to unify the api with SFDictFileCache 
62+         self ._getitem_non_locking  =  self ._getitem 
6163
6264    def  __len__ (self ) ->  int :
6365        with  self ._lock :
@@ -403,16 +405,20 @@ def __init__(
403405        if  os .path .exists (self .file_path ):
404406            self ._load ()
405407
406-     def  _getitem (
408+     def  _getitem_non_locking (
407409        self ,
408410        k : K ,
409411        * ,
410412        should_record_hits : bool  =  True ,
411413    ) ->  V :
412-         """Non-locking version of __getitem__. 
414+         """Non-locking version of __getitem__ of SFDictFileCache . 
413415
414416        This should only be used by internal functions when already 
415417        holding self._lock. 
418+ 
419+         Note that we do not overwrite _getitem because _getitem is used by 
420+         self._load to clear in-memory expired caches. Overwriting would cause 
421+         infinite recursive call. 
416422        """ 
417423        if  k  not  in   self ._cache :
418424            loaded  =  self ._load_if_should ()
Original file line number Diff line number Diff line change @@ -708,7 +708,7 @@ def find_cache(
708708            ocsp_response_validation_result  =  (
709709                OCSP_RESPONSE_VALIDATION_CACHE [cache_key ]
710710                if  lock_cache 
711-                 else  OCSP_RESPONSE_VALIDATION_CACHE ._getitem (cache_key )
711+                 else  OCSP_RESPONSE_VALIDATION_CACHE ._getitem_non_locking (cache_key )
712712            )
713713            try :
714714                # is_valid_time can raise exception if the cache 
Original file line number Diff line number Diff line change 11# Update this for the versions 
22# Don't change the forth version number from None 
3- VERSION  =  (2 , 8 , 2 , None )
3+ VERSION  =  (2 , 8 , 3 , None )
Original file line number Diff line number Diff line change @@ -104,6 +104,7 @@ def test_get(self):
104104        c ._entry_lifetime  =  NO_LIFETIME 
105105        c ["d" ] =  4 
106106        assert  c .get ("d" ) is  None 
107+         assert  c ._getitem_non_locking (1 ) ==  "a" 
107108
108109    def  test_items (self ):
109110        c  =  cache .SFDictCache ()
@@ -405,3 +406,25 @@ def test_clear(self, tmpdir):
405406        os .unlink (cache_path )
406407        c ["a" ] =  1 
407408        assert  os .path .exists (cache_path )
409+ 
410+     def  test_load_with_expired_entries (self , tmpdir ):
411+         # Test: https://snowflakecomputing.atlassian.net/browse/SNOW-698526 
412+ 
413+         # create cache first 
414+         cache_path  =  os .path .join (tmpdir , "cache.txt" )
415+         c1  =  cache .SFDictFileCache (file_path = cache_path )
416+         c1 ["a" ] =  1 
417+         c1 ._save ()
418+ 
419+         # load cache 
420+         c2  =  cache .SFDictFileCache (
421+             file_path = cache_path , entry_lifetime = int (NO_LIFETIME .total_seconds ())
422+         )
423+         c2 ["b" ] =  2 
424+         c2 ["c" ] =  3 
425+         # cache will expire immediately due to the NO_LIFETIME setting 
426+         # when loading again, clearing cache logic will be triggered 
427+         # load will trigger clear expired entries, and then further call _getitem 
428+         c2 ._load ()
429+ 
430+         assert  len (c2 ) ==  1  and  c2 ["a" ] ==  1  and  c2 ._getitem_non_locking ("a" ) ==  1 
    
 
   
 
     
   
   
          
     
  
    
     
 
    
      
     
 
     
    You can’t perform that action at this time.
  
 
    
  
     
    
      
        
     
 
       
      
     
   
 
    
    
  
 
  
 
     
    
0 commit comments