compiler: Write binary package files in checked code

859cfb8c8328f524709d9d4ac198fff5f72061292a25e32f75a59f62dda138d6
Alexis Sellier committed ago 1 parent b74f809e
compiler/radiance.rad +16 -11
1296 1296
        }
1297 1297
    }
1298 1298
    return PackageExports { count, entry: entryName };
1299 1299
}
1300 1300
1301 +
/// Write encoded binary RIL bytes into an existing directory.
1302 +
fn writePackage(bytes: &[u8], directory: *[u8], name: *[u8]) throws (Error) {
1303 +
    let mut path = [0 as u8; MAX_PATH_LEN];
1304 +
    let mut pos: u32 = 0;
1305 +
    for part in &[directory, "/", name, ".ril"] {
1306 +
        set pos += try mem::copy(&mut path[pos..MAX_PATH_LEN - 1], part) catch {
1307 +
            throw error(&["binary RIL output path is too long"]);
1308 +
        };
1309 +
    }
1310 +
    set path[pos] = 0;
1311 +
    if not unix::writeFile(&path[..pos], bytes) {
1312 +
        throw error(&["cannot write binary RIL package", name]);
1313 +
    }
1314 +
}
1315 +
1301 1316
/// Emit one binary RIL file per package into an existing directory.
1302 1317
unsafe fn emitPackages 'arena (
1303 1318
    ctx: &CompileContext,
1304 1319
    res: *unsafe mut resolver::Resolver 'arena,
1305 1320
    directory: *[u8]
1334 1349
                throw error(&["cannot collect binary RIL package", pkg.name]);
1335 1350
            };
1336 1351
            let length = try program::encode(&mut FN_ARENA[..], &image) catch {
1337 1352
                throw error(&["binary RIL output capacity exceeded", pkg.name]);
1338 1353
            };
1339 -
            let mut path: [u8; MAX_PATH_LEN] = undefined;
1340 -
            let mut pos: u32 = 0;
1341 -
            for part in &[directory, "/", pkg.name, ".ril"] {
1342 -
                set pos += try mem::copy(&mut path[pos..MAX_PATH_LEN - 1], part) catch {
1343 -
                    throw error(&["binary RIL output path is too long"]);
1344 -
                };
1345 -
            }
1346 -
            set path[pos] = 0;
1347 -
            if not unix::writeFile(&path[..pos], &FN_ARENA[..length]) {
1348 -
                throw error(&["cannot write binary RIL package", pkg.name]);
1349 -
            }
1354 +
            try writePackage(&FN_ARENA[..length], directory, pkg.name);
1350 1355
        }
1351 1356
    }
1352 1357
}
1353 1358
1354 1359
/// Match a qualified definition to its package name.
test/command +30 -0
93 93
    printf '%s\n' '/// Package fixture value.' 'constant value: u32 = 0;' > "$work/$name.rad"
94 94
    arguments="$arguments -pkg $name -mod $work/$name.rad"
95 95
done
96 96
accept "$arguments -pkg p -mod $work/p.rad -entry p -o $work/multiple.rv64"
97 97
timeout 10 "${RAD_EMULATOR:-emulator}" -run "$work/multiple.rv64"
98 +
99 +
# Binary package output preserves bytes across destinations and replacements.
100 +
mkdir "$work/packages"
101 +
accept "$arguments -pkg p -mod $work/p.rad -entry p -ril $work/packages"
102 +
for name in a b c p; do
103 +
    test -s "$work/packages/$name.ril"
104 +
done
105 +
cp "$work/packages/p.ril" "$work/expected.ril"
106 +
printf '%s\n' 'stale output bytes' >> "$work/packages/p.ril"
107 +
accept "-pkg p -mod $work/p.rad -ril $work/packages"
108 +
cmp "$work/expected.ril" "$work/packages/p.ril"
109 +
110 +
# MAX_PATH_LEN includes the terminating zero byte.
111 +
for length in 249 250 255 256; do
112 +
    leaf=$(awk -v n="$((length - ${#work} - 1))" 'BEGIN { for (i = 0; i < n; i++) printf "x" }')
113 +
    directory="$work/$leaf"
114 +
    if [ "$length" -eq 249 ]; then
115 +
        mkdir "$directory"
116 +
        accept "-pkg p -mod $work/p.rad -ril $directory"
117 +
        cmp "$work/expected.ril" "$directory/p.ril"
118 +
        reject "-pkg package -mod $work/p.rad -ril $directory" 'binary RIL output path is too long'
119 +
    else
120 +
        reject "-pkg p -mod $work/p.rad -ril $directory" 'binary RIL output path is too long'
121 +
    fi
122 +
done
123 +
reject "-pkg p -mod $work/p.rad -ril $work/missing" 'cannot write binary RIL package p'
124 +
mkdir -p "$work/blocked/p.ril"
125 +
reject "-pkg p -mod $work/p.rad -ril $work/blocked" 'cannot write binary RIL package p'
126 +
reject "-pkg p -mod $work/p.rad -mod absent.ras -ril $work/packages" 'binary RIL output requires Radiance source modules'
127 +
reject "-pkg p -mod $work/p.rad -start absent.ras -ril $work/packages" 'binary RIL output requires Radiance source modules'
98 128
echo "command tests: $checks passed"