Sfoglia il codice sorgente

fix: NULL-terminate vector-built argv — segfault in g_subprocess_newv

Invercargill Vector.to_array() returns exactly-sized arrays without the
NULL sentinel GLib spawn helpers and string.joinv require; the byte after
the array is heap luck, so usmrad segfaulted (or corrupted argv) at
varying spawn sites per boot. All vector-built argument lists now flow
through Argv.from_vector (explicit new string[n+1] fill, trailing zeroed
slot — the same pattern as usm_argv). Also replaces the select/joinv
unmet-deps listing, which emitted a trailing separator.
clanker 1 mese fa
parent
commit
0506941775
3 ha cambiato i file con 43 aggiunte e 9 eliminazioni
  1. 3 3
      src/rad/Source.vala
  2. 12 6
      src/rad/System.vala
  3. 28 0
      src/rad/Usmrad.vala

+ 3 - 3
src/rad/Source.vala

@@ -42,7 +42,7 @@ public class Source : Object {
         command.add(branch);
         command.add(repo_url);
         command.add(repo_dir);
-        run_command(command.to_array());
+        run_command(Argv.from_vector(command));
     }
 
     /**
@@ -68,7 +68,7 @@ public class Source : Object {
         try {
             // Read-only: capture both streams so the thrown message keeps
             // git's diagnostics instead of splicing them into the log
-            var proc = new Subprocess.newv(command.to_array(),
+            var proc = new Subprocess.newv(Argv.from_vector(command),
                 SubprocessFlags.STDOUT_PIPE | SubprocessFlags.STDERR_PIPE);
             string git_stdout;
             string git_stderr;
@@ -111,7 +111,7 @@ public class Source : Object {
         foreach(var argument in arguments) {
             command.add(argument);
         }
-        run_command(command.to_array());
+        run_command(Argv.from_vector(command));
     }
 
     /**

+ 12 - 6
src/rad/System.vala

@@ -162,16 +162,16 @@ public class System : Object {
         }
 
         if(usm_names.length > 0) {
-            Log.info(@"Installing USM packages: $(string.joinv(" ", usm_names.to_array()))");
+            Log.info(@"Installing USM packages: $(string.joinv(" ", Argv.from_vector(usm_names)))");
             var arguments = new Vector<string>();
             arguments.add("install");
             arguments.add("-y");
             arguments.add_all(usm_names);
-            yield run_usm_async(arguments.to_array());
+            yield run_usm_async(Argv.from_vector(arguments));
         }
 
         if(spm_names.length > 0) {
-            Log.info(@"Installing system packages: $(string.joinv(" ", spm_names.to_array()))");
+            Log.info(@"Installing system packages: $(string.joinv(" ", Argv.from_vector(spm_names)))");
             var system_installed = false;
             try {
                 system_installed = yield spm.install(spm_names, event => log_install_progress(event));
@@ -180,15 +180,21 @@ public class System : Object {
                 throw new RadError.DEPLOY(@"Could not run the system package manager install: $(e.message)");
             }
             if(!system_installed) {
-                throw new RadError.DEPLOY(@"The system package manager failed to install: $(string.joinv(" ", spm_names.to_array()))");
+                throw new RadError.DEPLOY(@"The system package manager failed to install: $(string.joinv(" ", Argv.from_vector(spm_names)))");
             }
         }
 
         var recheck = new Usm.ResourceFinder();
         var unmet = missing.where(r => !recheck.has_resource(r)).to_vector();
         if(unmet.length > 0) {
-            var listing = string.joinv(", ", unmet.select<string>(r => r.to_string()).to_array());
-            throw new RadError.DEPENDENCY(@"Dependencies not satisfied after installation: $listing");
+            var listing = new StringBuilder();
+            foreach(var dependency in unmet) {
+                if(listing.len > 0) {
+                    listing.append(", ");
+                }
+                listing.append(dependency.to_string());
+            }
+            throw new RadError.DEPENDENCY(@"Dependencies not satisfied after installation: $(listing.str)");
         }
     }
 

+ 28 - 0
src/rad/Usmrad.vala

@@ -47,6 +47,34 @@ public class Log {
     }
 }
 
+/**
+ * argv construction for spawned commands and joined argument strings.
+ *
+ * Invercargill's {@link Invercargill.DataStructures.Vector.to_array} returns
+ * exactly-sized arrays without the NULL sentinel GLib's spawn helpers and
+ * {@link string.joinv} require — an unterminated argv crashes inside
+ * g_subprocess_newv's g_strdupv. Every vector-built argument list therefore
+ * flows through {@link from_vector}, whose trailing zeroed slot terminates
+ * the array the same way a Vala literal or explicit `new string[n]` fill
+ * does.
+ */
+public class Argv {
+
+    /**
+     * A NULL-terminated copy of {@link command}: one slot longer than the
+     * vector, with the final slot left zeroed as the sentinel.
+     */
+    public static string[] from_vector(Invercargill.DataStructures.Vector<string> command) {
+        var size = (int)command.length;
+        var argv = new string[size + 1];
+        var index = 0;
+        foreach(var argument in command) {
+            argv[index++] = argument;
+        }
+        return argv;
+    }
+}
+
 /**
  * usmrad configuration, parsed from the USMRAD_* environment.
  */