* Don't allow derivations with fixed and non-fixed outputs.
This commit is contained in:
		
							parent
							
								
									b2027f70d9
								
							
						
					
					
						commit
						c8606664ab
					
				
					 1 changed files with 40 additions and 45 deletions
				
			
		|  | @ -394,53 +394,48 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) | ||||||
|         throw EvalError(format("derivation names are not allowed to end in `%1%'") |         throw EvalError(format("derivation names are not allowed to end in `%1%'") | ||||||
|             % drvExtension); |             % drvExtension); | ||||||
| 
 | 
 | ||||||
|     /* Construct the "masked" store derivation, which is the final one
 |     if (outputHash != "") { | ||||||
|        except that in the list of outputs, the output paths are empty, |         /* Handle fixed-output derivations. */ | ||||||
|        and the corresponding environment variables have an empty |         if (outputs.size() != 1 || *(outputs.begin()) != "out") | ||||||
|        value.  This ensures that changes in the set of output names do |             throw Error("multiple outputs are not supported in fixed-output derivations"); | ||||||
|        get reflected in the hash. |  | ||||||
|          |          | ||||||
|        However, for fixed-output derivations, we can compute the |         HashType ht = parseHashType(outputHashAlgo); | ||||||
|        output path directly, so we don't need this. */ |         if (ht == htUnknown) | ||||||
|     bool fixedOnly = true; |             throw EvalError(format("unknown hash algorithm `%1%'") % outputHashAlgo); | ||||||
|     foreach (StringSet::iterator, i, outputs) { |         Hash h(ht); | ||||||
|         if (*i != "out" || outputHash == "") { |         if (outputHash.size() == h.hashSize * 2) | ||||||
|             drv.env[*i] = ""; |             /* hexadecimal representation */ | ||||||
|             drv.outputs[*i] = DerivationOutput("", "", ""); |             h = parseHash(ht, outputHash); | ||||||
|             fixedOnly = false; |         else if (outputHash.size() == hashLength32(h)) | ||||||
|         } else { |             /* base-32 representation */ | ||||||
|             /* If an output hash was given, check it, and compute the
 |             h = parseHash32(ht, outputHash); | ||||||
|                output path. */ |         else | ||||||
|             HashType ht = parseHashType(outputHashAlgo); |             throw Error(format("hash `%1%' has wrong length for hash type `%2%'") | ||||||
|             if (ht == htUnknown) |                 % outputHash % outputHashAlgo); | ||||||
|                 throw EvalError(format("unknown hash algorithm `%1%'") % outputHashAlgo); |         string s = outputHash; | ||||||
|             Hash h(ht); |         outputHash = printHash(h); | ||||||
|             if (outputHash.size() == h.hashSize * 2) |         if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo; | ||||||
|                 /* hexadecimal representation */ |          | ||||||
|                 h = parseHash(ht, outputHash); |         Path outPath = makeFixedOutputPath(outputHashRecursive, ht, h, drvName); | ||||||
|             else if (outputHash.size() == hashLength32(h)) |         drv.env["out"] = outPath; | ||||||
|                 /* base-32 representation */ |         drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash); | ||||||
|                 h = parseHash32(ht, outputHash); |  | ||||||
|             else |  | ||||||
|                 throw Error(format("hash `%1%' has wrong length for hash type `%2%'") |  | ||||||
|                     % outputHash % outputHashAlgo); |  | ||||||
|             string s = outputHash; |  | ||||||
|             outputHash = printHash(h); |  | ||||||
|             if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo; |  | ||||||
|             Path outPath = makeFixedOutputPath(outputHashRecursive, ht, h, drvName); |  | ||||||
|             drv.env[*i] = outPath; |  | ||||||
|             drv.outputs[*i] = DerivationOutput(outPath, outputHashAlgo, outputHash); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Use the masked derivation expression to compute the output
 |     else { | ||||||
|        path.  !!! Isn't it a potential security problem that the name |         /* Construct the "masked" store derivation, which is the final
 | ||||||
|        of each output path (including the suffix) isn't taken into |            one except that in the list of outputs, the output paths | ||||||
|        account?  For instance, changing the suffix for one path |            are empty, and the corresponding environment variables have | ||||||
|        (‘i->first == "out" ...’) doesn't affect the hash of the |            an empty value.  This ensures that changes in the set of | ||||||
|        others.  Is that exploitable? */ |            output names do get reflected in the hash. */ | ||||||
|     if (!fixedOnly) { |         foreach (StringSet::iterator, i, outputs) { | ||||||
|  |             drv.env[*i] = ""; | ||||||
|  |             drv.outputs[*i] = DerivationOutput("", "", ""); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* Use the masked derivation expression to compute the output
 | ||||||
|  |            path. */ | ||||||
|         Hash h = hashDerivationModulo(drv); |         Hash h = hashDerivationModulo(drv); | ||||||
|  |          | ||||||
|         foreach (DerivationOutputs::iterator, i, drv.outputs) |         foreach (DerivationOutputs::iterator, i, drv.outputs) | ||||||
|             if (i->second.path == "") { |             if (i->second.path == "") { | ||||||
|                 Path outPath = makeOutputPath(i->first, h, drvName); |                 Path outPath = makeOutputPath(i->first, h, drvName); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue