| 
					
				 | 
			
			
				@@ -4837,25 +4837,63 @@ or_state_validate(or_state_t *old_state, or_state_t *state, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Replace the current persistent state with <b>new_state</b> */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 or_state_set(or_state_t *new_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   char *err = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int ret = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tor_assert(new_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   config_free(&state_format, global_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   global_state = new_state; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (entry_guards_parse_state(global_state, 1, &err)<0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     log_warn(LD_GENERAL,"%s",err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tor_free(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ret = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (rep_hist_load_state(global_state, &err)<0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tor_free(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ret = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (circuit_build_times_parse_state(&circ_times, global_state, &err) < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     log_warn(LD_GENERAL,"%s",err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tor_free(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ret = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Save a broken state file to a backup location. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+or_state_save_broken(char *fname) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  file_status_t status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t len = strlen(fname)+16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  char *fname2 = tor_malloc(len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i = 0; i < 100; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tor_snprintf(fname2, len, "%s.%d", fname, i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    status = file_status(fname2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (status == FN_NOENT) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (i == 100) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             "state files to move aside. Discarding the old state file.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             fname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    unlink(fname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             "to \"%s\".  This could be a bug in Tor; please tell " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             "the developers.", fname, fname2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (rename(fname, fname2) < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               "OS gave an error of %s", strerror(errno)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_free(fname2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Reload the persistent state from disk, generating a new state as needed. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -4917,31 +4955,8 @@ or_state_load(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              " This is a bug in Tor."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     goto done; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else if (badstate && contents) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    int i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    file_status_t status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    size_t len = strlen(fname)+16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    char *fname2 = tor_malloc(len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (i = 0; i < 100; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      tor_snprintf(fname2, len, "%s.%d", fname, i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      status = file_status(fname2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (status == FN_NOENT) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (i == 100) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-               "state files to move aside. Discarding the old state file.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-               fname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      unlink(fname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-               "to \"%s\".  This could be a bug in Tor; please tell " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-               "the developers.", fname, fname2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (rename(fname, fname2) < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                 "OS gave an error of %s", strerror(errno)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    tor_free(fname2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    or_state_save_broken(fname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tor_free(contents); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     config_free(&state_format, new_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -4953,7 +4968,9 @@ or_state_load(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     log_info(LD_GENERAL, "Initialized state"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  or_state_set(new_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (or_state_set(new_state) == -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    or_state_save_broken(fname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   new_state = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (!contents) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     global_state->next_write = 0; 
			 |