$OpenBSD: patch-src_runtime_save_c,v 1.1 2009/11/17 10:45:00 pirofti Exp $

Fall back to saved_runtime_path if os_get_runtime_executable_path(0)
returns NULL.

Search for the current build_id when loading the runtime from disk to
save an executable core.  This provided some protection against
accidentally embedding a core in the wrong runtime, which may be more
likely when using saved_runtime_path.

--- src/runtime/save.c.orig	Sat Jan 17 02:43:57 2009
+++ src/runtime/save.c	Mon Jun 29 07:53:42 2009
@@ -376,6 +376,25 @@ save_to_filehandle(FILE *file, char *filename, lispobj
     exit(0);
 }
 
+/* Check if the build_id for the current runtime is present in a
+ * buffer. */
+int
+check_runtime_build_id(void *buf, size_t size)
+{
+    size_t idlen;
+    char *pos;
+
+    idlen = strlen(build_id) - 1;
+    while ((pos = memchr(buf, build_id[0], size)) != NULL) {
+        size -= (pos + 1) - (char *)buf;
+        buf = (pos + 1);
+        if (idlen <= size && memcmp(buf, build_id + 1, idlen) == 0)
+            return 1;
+    }
+
+    return 0;
+}
+
 /* Slurp the executable portion of the runtime into a malloced buffer
  * and return it.  Places the size in bytes of the runtime into
  * 'size_out'.  Returns NULL if the runtime cannot be loaded from
@@ -407,6 +426,12 @@ load_runtime(char *runtime_path, size_t *size_out)
         goto lose;
     }
 
+    if (!check_runtime_build_id(buf, size)) {
+        fprintf(stderr, "Failed to locate current build_id in runtime: %s\n",
+            runtime_path);
+        goto lose;
+    }
+
     fclose(input);
     *size_out = size;
     return buf;
@@ -453,15 +478,19 @@ prepare_to_save(char *filename, boolean prepend_runtim
     char *runtime_path;
 
     if (prepend_runtime) {
-        runtime_path = os_get_runtime_executable_path();
+        runtime_path = os_get_runtime_executable_path(0);
 
-        if (runtime_path == NULL) {
+        if (runtime_path == NULL && saved_runtime_path == NULL) {
             fprintf(stderr, "Unable to get default runtime path.\n");
             return NULL;
         }
 
-        *runtime_bytes = load_runtime(runtime_path, runtime_size);
-        free(runtime_path);
+        if (runtime_path == NULL)
+            *runtime_bytes = load_runtime(saved_runtime_path, runtime_size);
+        else {
+            *runtime_bytes = load_runtime(runtime_path, runtime_size);
+            free(runtime_path);
+        }
 
         if (*runtime_bytes == NULL)
             return 0;
