Merge pull request #3320 from Skgland/all-pure-rust
add a feature for enabling all features that don't pull in non pure rust dependencies
This commit is contained in:
2
.github/actions/setup-rust/cleanup.sh
vendored
2
.github/actions/setup-rust/cleanup.sh
vendored
@@ -4,7 +4,7 @@ set -e
|
|||||||
echo Cleanup workspace build artifacts and extra target output
|
echo Cleanup workspace build artifacts and extra target output
|
||||||
|
|
||||||
# clean just the direct members of the current workspace, use cargo metadata to generalize to all rust projects
|
# clean just the direct members of the current workspace, use cargo metadata to generalize to all rust projects
|
||||||
cargo clean -p `cargo metadata --no-deps --offline --format-version 1 | jq -r '[.workspace_members[]|split(" ")|.[0]]|join(" ")'`
|
cargo clean --workspace
|
||||||
|
|
||||||
# remove directories in /target/ that are not named `debug` or `release`
|
# remove directories in /target/ that are not named `debug` or `release`
|
||||||
before=`du -s target | awk '{print $1}'`
|
before=`du -s target | awk '{print $1}'`
|
||||||
|
|||||||
12
.github/workflows/check_features.sh
vendored
Executable file
12
.github/workflows/check_features.sh
vendored
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Checking all feature at once"
|
||||||
|
cargo check -q --all-targets --all-features "$@"
|
||||||
|
|
||||||
|
features=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name = "scryer-prolog") | .features | keys | join(" ")')
|
||||||
|
|
||||||
|
for feature in ${features} ; do
|
||||||
|
echo "Checking feature ${feature} in isolation"
|
||||||
|
cargo check -q --all-targets --no-default-features --features=${feature} "$@"
|
||||||
|
done
|
||||||
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@@ -53,10 +53,10 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# operating systems
|
# operating systems
|
||||||
- { os: windows-latest, rust-version: stable, target: 'x86_64-pc-windows-msvc', publish: true }
|
- { os: windows-latest, rust-version: stable, target: 'x86_64-pc-windows-msvc', publish: true, check-features: true }
|
||||||
- { os: macos-latest, rust-version: stable, target: 'x86_64-apple-darwin', publish: true }
|
- { os: macos-latest, rust-version: stable, target: 'x86_64-apple-darwin', publish: true, check-features: true }
|
||||||
# architectures
|
# architectures
|
||||||
- { os: ubuntu-22.04, rust-version: stable, target: 'x86_64-unknown-linux-gnu', publish: true }
|
- { os: ubuntu-22.04, rust-version: stable, target: 'x86_64-unknown-linux-gnu', publish: true, check-features: true }
|
||||||
- { os: ubuntu-22.04, rust-version: stable, target: 'i686-unknown-linux-gnu', publish: true }
|
- { os: ubuntu-22.04, rust-version: stable, target: 'i686-unknown-linux-gnu', publish: true }
|
||||||
# FIXME(issue #2138): run wasm tests, failing to run since https://github.com/mthom/scryer-prolog/pull/2137 removed wasm-pack
|
# FIXME(issue #2138): run wasm tests, failing to run since https://github.com/mthom/scryer-prolog/pull/2137 removed wasm-pack
|
||||||
- { os: ubuntu-22.04, rust-version: nightly, target: 'wasm32-unknown-unknown', publish: true, args: '--no-default-features' , test-args: '--no-run --no-default-features', use_swap: true }
|
- { os: ubuntu-22.04, rust-version: nightly, target: 'wasm32-unknown-unknown', publish: true, args: '--no-default-features' , test-args: '--no-run --no-default-features', use_swap: true }
|
||||||
@@ -88,9 +88,14 @@ jobs:
|
|||||||
# Build and test.
|
# Build and test.
|
||||||
- name: Build library
|
- name: Build library
|
||||||
run: cargo build --all-targets --target ${{ matrix.target }} ${{ matrix.args }} --verbose
|
run: cargo build --all-targets --target ${{ matrix.target }} ${{ matrix.args }} --verbose
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: cargo test --target ${{ matrix.target }} ${{ matrix.test-args }} --all
|
run: cargo test --target ${{ matrix.target }} ${{ matrix.test-args }} --all
|
||||||
|
|
||||||
|
- name: Check features
|
||||||
|
if: matrix.check-features
|
||||||
|
run: bash ./.github/workflows/check_features.sh --target ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Check miri
|
- name: Check miri
|
||||||
if: matrix.miri
|
if: matrix.miri
|
||||||
run: cargo miri test --target ${{ matrix.target }} ${{ matrix.args }}
|
run: cargo miri test --target ${{ matrix.target }} ${{ matrix.args }}
|
||||||
|
|||||||
22
Cargo.toml
22
Cargo.toml
@@ -17,16 +17,27 @@ rust-version = "1.93.1"
|
|||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ffi", "repl", "hostname", "tls", "http", "crypto-full"]
|
default = ["all-simple-cross", "tls", "http"]
|
||||||
|
# activates all features that depend on no non pure-rust dependencies
|
||||||
|
#
|
||||||
|
# currently does not include
|
||||||
|
# ffi due to libffi
|
||||||
|
# tls, http due to openssl
|
||||||
|
# crypto-full due to ring
|
||||||
|
all-pure = ["repl", "hostname"]
|
||||||
# enables all features that are simple to get working for cross-compliation
|
# enables all features that are simple to get working for cross-compliation
|
||||||
# currently all but tls, http as those depend on openssl
|
# currently all but tls, http as those depend on openssl
|
||||||
all-simple-cross = ["ffi", "repl", "hostname", "crypto-full"]
|
all-simple-cross = ["all-pure", "ffi", "crypto-full"]
|
||||||
ffi = ["dep:libffi"]
|
ffi = ["dep:libffi"]
|
||||||
repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"]
|
repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"]
|
||||||
hostname = ["dep:hostname"]
|
hostname = ["dep:hostname"]
|
||||||
tls = ["dep:native-tls"]
|
tls = ["dep:native-tls"]
|
||||||
http = ["dep:warp", "dep:reqwest"]
|
http = ["dep:warp", "dep:reqwest"]
|
||||||
crypto-full = []
|
# crypto function that require non pure-rust dependencies
|
||||||
|
crypto-full = ["dep:ring"]
|
||||||
|
|
||||||
|
[lints.clippy]
|
||||||
|
collapsible_match = "allow"
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
unexpected_cfgs = { level = "deny", check-cfg = [
|
unexpected_cfgs = { level = "deny", check-cfg = [
|
||||||
@@ -34,7 +45,6 @@ unexpected_cfgs = { level = "deny", check-cfg = [
|
|||||||
] }
|
] }
|
||||||
function_casts_as_integer = "deny"
|
function_casts_as_integer = "deny"
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
proc-macro2 = "1.0.86"
|
proc-macro2 = "1.0.86"
|
||||||
quote = "1.0.36"
|
quote = "1.0.36"
|
||||||
@@ -73,7 +83,9 @@ ordered-float = "5.0.0"
|
|||||||
phf = { version = "0.11", features = ["macros"] }
|
phf = { version = "0.11", features = ["macros"] }
|
||||||
puruspe = "0.4.1"
|
puruspe = "0.4.1"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
ring = { version = "0.17.8", features = ["wasm32_unknown_unknown_js"] }
|
ring = { version = "0.17.8", features = [
|
||||||
|
"wasm32_unknown_unknown_js",
|
||||||
|
], optional = true }
|
||||||
ripemd = "0.1.3"
|
ripemd = "0.1.3"
|
||||||
roxmltree = "0.20.0"
|
roxmltree = "0.20.0"
|
||||||
ryu = "1.0.18"
|
ryu = "1.0.18"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ use ordered_float::OrderedFloat;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
use std::io::PipeReader;
|
||||||
|
use std::io::PipeWriter;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
@@ -22,8 +24,6 @@ use std::ptr;
|
|||||||
use std::ptr::addr_of_mut;
|
use std::ptr::addr_of_mut;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
use crate::machine::streams::{PipeReader, PipeWriter};
|
|
||||||
|
|
||||||
macro_rules! arena_alloc {
|
macro_rules! arena_alloc {
|
||||||
($e:expr, $arena:expr) => {{
|
($e:expr, $arena:expr) => {{
|
||||||
let result = $e;
|
let result = $e;
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ impl BranchCodeStack {
|
|||||||
settings.trust_me()
|
settings.trust_me()
|
||||||
});
|
});
|
||||||
|
|
||||||
combined_code.extend(code.into_iter());
|
combined_code.extend(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1236,7 +1236,7 @@ impl CodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.skeleton.clauses.push_back(clause_index_info);
|
self.skeleton.clauses.push_back(clause_index_info);
|
||||||
code.extend(clause_code.into_iter());
|
code.extend(clause_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
let index_code = if clauses_len > 1 || self.settings.is_extensible {
|
let index_code = if clauses_len > 1 || self.settings.is_extensible {
|
||||||
@@ -1313,7 +1313,7 @@ impl CodeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
code.extend(code_segment.into_iter());
|
code.extend(code_segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(code)
|
Ok(code)
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ pub mod wasm;
|
|||||||
/// The entry point for the Scryer Prolog CLI.
|
/// The entry point for the Scryer Prolog CLI.
|
||||||
pub fn run_binary() -> std::process::ExitCode {
|
pub fn run_binary() -> std::process::ExitCode {
|
||||||
use crate::atom_table::Atom;
|
use crate::atom_table::Atom;
|
||||||
|
|
||||||
|
#[cfg(feature = "repl")]
|
||||||
use crate::machine::INTERRUPT;
|
use crate::machine::INTERRUPT;
|
||||||
|
|
||||||
#[cfg(feature = "repl")]
|
#[cfg(feature = "repl")]
|
||||||
|
|||||||
@@ -247,11 +247,12 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
self.trail
|
self.trail
|
||||||
.push((TrailRef::pstr_loc(pstr_loc_idx), old_cell));
|
.push((TrailRef::pstr_loc(pstr_loc_idx), old_cell));
|
||||||
|
|
||||||
let old_tail_idx = if (pstr_loc + offset + 1) % Heap::heap_cell_alignment() == 0 {
|
let old_tail_idx =
|
||||||
cell_index!(pstr_loc + offset) + 2
|
if (pstr_loc + offset + 1).is_multiple_of(Heap::heap_cell_alignment()) {
|
||||||
} else {
|
cell_index!(pstr_loc + offset) + 2
|
||||||
cell_index!(pstr_loc + offset) + 1
|
} else {
|
||||||
};
|
cell_index!(pstr_loc + offset) + 1
|
||||||
|
};
|
||||||
|
|
||||||
let tail_cell = self.target[old_tail_idx];
|
let tail_cell = self.target[old_tail_idx];
|
||||||
|
|
||||||
|
|||||||
@@ -549,7 +549,7 @@ impl VariableClassifier {
|
|||||||
|
|
||||||
let first_branch_num = Arc::new(self.current_branch_num.split());
|
let first_branch_num = Arc::new(self.current_branch_num.split());
|
||||||
let branches: Vec<_> = std::iter::once(head)
|
let branches: Vec<_> = std::iter::once(head)
|
||||||
.chain(unfold_by_str(tail, atom!(";")).into_iter())
|
.chain(unfold_by_str(tail, atom!(";")))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut branch_numbers = vec![first_branch_num];
|
let mut branch_numbers = vec![first_branch_num];
|
||||||
@@ -571,7 +571,7 @@ impl VariableClassifier {
|
|||||||
self.current_branch_num.halve_delta(),
|
self.current_branch_num.halve_delta(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let iter = branches.into_iter().zip(branch_numbers.into_iter());
|
let iter = branches.into_iter().zip(branch_numbers);
|
||||||
let final_disjunct_loc = state_stack.len();
|
let final_disjunct_loc = state_stack.len();
|
||||||
|
|
||||||
for (term, branch_num) in iter.rev() {
|
for (term, branch_num) in iter.rev() {
|
||||||
|
|||||||
@@ -577,7 +577,7 @@ impl Heap {
|
|||||||
// takes a heap index, returns a cell index
|
// takes a heap index, returns a cell index
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn pstr_tail_idx(pstr_zero_byte_loc: usize) -> usize {
|
pub const fn pstr_tail_idx(pstr_zero_byte_loc: usize) -> usize {
|
||||||
if (pstr_zero_byte_loc + 1) % Heap::heap_cell_alignment() == 0 {
|
if (pstr_zero_byte_loc + 1).is_multiple_of(Heap::heap_cell_alignment()) {
|
||||||
cell_index!(pstr_zero_byte_loc) + 2
|
cell_index!(pstr_zero_byte_loc) + 2
|
||||||
} else {
|
} else {
|
||||||
cell_index!(pstr_zero_byte_loc) + 1
|
cell_index!(pstr_zero_byte_loc) + 1
|
||||||
|
|||||||
@@ -937,6 +937,7 @@ impl Permission {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[cfg_attr(not(feature = "ffi"), expect(dead_code))]
|
||||||
pub(crate) enum DomainErrorType {
|
pub(crate) enum DomainErrorType {
|
||||||
IOMode,
|
IOMode,
|
||||||
NotLessThanZero,
|
NotLessThanZero,
|
||||||
@@ -987,6 +988,7 @@ impl DomainErrorType {
|
|||||||
|
|
||||||
// from 7.12.2 f) of 13211-1:1995
|
// from 7.12.2 f) of 13211-1:1995
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[cfg_attr(not(feature = "ffi"), expect(dead_code))]
|
||||||
pub(crate) enum RepFlag {
|
pub(crate) enum RepFlag {
|
||||||
Character,
|
Character,
|
||||||
CharacterCode,
|
CharacterCode,
|
||||||
@@ -1178,6 +1180,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(not(feature = "ffi"), expect(dead_code))]
|
||||||
pub enum ExistenceError {
|
pub enum ExistenceError {
|
||||||
Module(Atom),
|
Module(Atom),
|
||||||
ModuleSource(ModuleSource),
|
ModuleSource(ModuleSource),
|
||||||
|
|||||||
@@ -548,8 +548,7 @@ impl MachineState {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use strict_add once msrv is >= 1.91.0
|
self.cwil.global_count = self.cwil.global_count.strict_add(1);
|
||||||
self.cwil.global_count = self.cwil.global_count.checked_add(1).unwrap();
|
|
||||||
|
|
||||||
if let Some(&(ref limit, block)) = self.cwil.limits.last() {
|
if let Some(&(ref limit, block)) = self.cwil.limits.last() {
|
||||||
if self.cwil.local_count == *limit {
|
if self.cwil.local_count == *limit {
|
||||||
@@ -651,7 +650,7 @@ impl MachineState {
|
|||||||
mut var_list: Vec<(VarKey, HeapCellValue, usize)>,
|
mut var_list: Vec<(VarKey, HeapCellValue, usize)>,
|
||||||
singleton_heap_list: HeapCellValue,
|
singleton_heap_list: HeapCellValue,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
|
var_list.sort_by_key(|(_, _, idx_1)| *idx_1);
|
||||||
|
|
||||||
let singleton_addr = self.registers[3];
|
let singleton_addr = self.registers[3];
|
||||||
unify_fn!(*self, singleton_heap_list, singleton_addr);
|
unify_fn!(*self, singleton_heap_list, singleton_addr);
|
||||||
@@ -1128,8 +1127,7 @@ impl CWIL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_limit(&mut self, mut limit: u128, block: usize) -> u128 {
|
pub(crate) fn add_limit(&mut self, mut limit: u128, block: usize) -> u128 {
|
||||||
// use strict_add once msrv is >= 1.91.0
|
limit = limit.strict_add(self.local_count);
|
||||||
limit = limit.checked_add(self.local_count).unwrap();
|
|
||||||
|
|
||||||
match self.limits.last() {
|
match self.limits.last() {
|
||||||
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
||||||
|
|||||||
@@ -195,8 +195,7 @@ impl Stack {
|
|||||||
// exposed provenance, we need to expose the provenance here, even though we don't
|
// exposed provenance, we need to expose the provenance here, even though we don't
|
||||||
// actually use the value for anything. This is a reminder that `expose_provenance`
|
// actually use the value for anything. This is a reminder that `expose_provenance`
|
||||||
// isn't just a cast from a pointer to an integer but has actual side effects.
|
// isn't just a cast from a pointer to an integer but has actual side effects.
|
||||||
// FIXME(msrv) remove the as_ptr() call once MSRV reaches 1.89.0
|
cell_ptr.expose_provenance();
|
||||||
cell_ptr.as_ptr().expose_provenance();
|
|
||||||
|
|
||||||
offset += mem::size_of::<HeapCellValue>();
|
offset += mem::size_of::<HeapCellValue>();
|
||||||
}
|
}
|
||||||
@@ -228,8 +227,7 @@ impl Stack {
|
|||||||
// exposed provenance, we need to expose the provenance here, even though we don't
|
// exposed provenance, we need to expose the provenance here, even though we don't
|
||||||
// actually use the value for anything. This is a reminder that `expose_provenance`
|
// actually use the value for anything. This is a reminder that `expose_provenance`
|
||||||
// isn't just a cast from a pointer to an integer but has actual side effects.
|
// isn't just a cast from a pointer to an integer but has actual side effects.
|
||||||
// FIXME(msrv) remove as_ptr() call once msrv reaches 1.89.0
|
cell_ptr.expose_provenance();
|
||||||
cell_ptr.as_ptr().expose_provenance();
|
|
||||||
|
|
||||||
offset += mem::size_of::<HeapCellValue>();
|
offset += mem::size_of::<HeapCellValue>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ use std::fmt::Debug;
|
|||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::PipeReader;
|
||||||
|
use std::io::PipeWriter;
|
||||||
use std::io::{Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
|
use std::io::{Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::net::{Shutdown, TcpStream};
|
use std::net::{Shutdown, TcpStream};
|
||||||
@@ -38,9 +40,6 @@ use native_tls::TlsStream;
|
|||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use warp::hyper;
|
use warp::hyper;
|
||||||
|
|
||||||
mod compat;
|
|
||||||
pub use compat::*;
|
|
||||||
|
|
||||||
#[derive(Debug, Specifier, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Specifier, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[bits = 1]
|
#[bits = 1]
|
||||||
pub enum StreamType {
|
pub enum StreamType {
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
#[cfg(rust_version = "1.87.0")]
|
|
||||||
pub use ge_1_87_0::{PipeReader, PipeWriter};
|
|
||||||
|
|
||||||
#[cfg(not(rust_version = "1.87.0"))]
|
|
||||||
pub use lt_1_87_0::{PipeReader, PipeWriter};
|
|
||||||
|
|
||||||
#[cfg(not(rust_version = "1.87.0"))]
|
|
||||||
pub(crate) use lt_1_87_0::PipeReaderInner;
|
|
||||||
|
|
||||||
#[cfg(not(rust_version = "1.87.0"))]
|
|
||||||
mod lt_1_87_0 {
|
|
||||||
use std::process::{ChildStderr, ChildStdout};
|
|
||||||
|
|
||||||
pub type PipeWriter = std::process::ChildStdin;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct PipeReader(pub(crate) PipeReaderInner);
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) enum PipeReaderInner {
|
|
||||||
Stdout(ChildStdout),
|
|
||||||
Stderr(ChildStderr),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::io::Read for PipeReader {
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
|
||||||
match &mut self.0 {
|
|
||||||
PipeReaderInner::Stdout(child_stdout) => child_stdout.read(buf),
|
|
||||||
PipeReaderInner::Stderr(child_stderr) => child_stderr.read(buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_vectored(
|
|
||||||
&mut self,
|
|
||||||
bufs: &mut [std::io::IoSliceMut<'_>],
|
|
||||||
) -> std::io::Result<usize> {
|
|
||||||
match &mut self.0 {
|
|
||||||
PipeReaderInner::Stdout(child_stdout) => child_stdout.read_vectored(bufs),
|
|
||||||
PipeReaderInner::Stderr(child_stderr) => child_stderr.read_vectored(bufs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
|
|
||||||
match &mut self.0 {
|
|
||||||
PipeReaderInner::Stdout(child_stdout) => child_stdout.read_to_end(buf),
|
|
||||||
PipeReaderInner::Stderr(child_stderr) => child_stderr.read_to_end(buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
|
|
||||||
match &mut self.0 {
|
|
||||||
PipeReaderInner::Stdout(child_stdout) => child_stdout.read_to_string(buf),
|
|
||||||
PipeReaderInner::Stderr(child_stderr) => child_stderr.read_to_string(buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
|
|
||||||
match &mut self.0 {
|
|
||||||
PipeReaderInner::Stdout(child_stdout) => child_stdout.read_exact(buf),
|
|
||||||
PipeReaderInner::Stderr(child_stderr) => child_stderr.read_exact(buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(rust_version = "1.87.0")]
|
|
||||||
mod ge_1_87_0 {
|
|
||||||
#![allow(clippy::incompatible_msrv)]
|
|
||||||
|
|
||||||
pub type PipeReader = std::io::PipeReader;
|
|
||||||
pub type PipeWriter = std::io::PipeWriter;
|
|
||||||
}
|
|
||||||
@@ -53,7 +53,6 @@ use std::mem;
|
|||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
use std::net::{TcpListener, TcpStream};
|
use std::net::{TcpListener, TcpStream};
|
||||||
use std::num::NonZeroU32;
|
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::process::Child;
|
use std::process::Child;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
@@ -74,11 +73,13 @@ use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifier
|
|||||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||||
|
|
||||||
use blake2::{Blake2b512, Blake2s256};
|
use blake2::{Blake2b512, Blake2s256};
|
||||||
use ring::rand::{SecureRandom, SystemRandom};
|
|
||||||
use ring::{digest, hkdf, hmac, pbkdf2};
|
|
||||||
|
|
||||||
#[cfg(feature = "crypto-full")]
|
#[cfg(feature = "crypto-full")]
|
||||||
use ring::aead;
|
use ring::{
|
||||||
|
aead, digest, hkdf, hmac, pbkdf2,
|
||||||
|
rand::{SecureRandom, SystemRandom},
|
||||||
|
};
|
||||||
|
|
||||||
use ripemd::{Digest, Ripemd160};
|
use ripemd::{Digest, Ripemd160};
|
||||||
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
|
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
|
||||||
|
|
||||||
@@ -96,8 +97,6 @@ use roxmltree;
|
|||||||
use futures::future;
|
use futures::future;
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use tokio::runtime::Handle;
|
|
||||||
use tokio::task;
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use warp::hyper::header::{HeaderName, HeaderValue};
|
use warp::hyper::header::{HeaderName, HeaderValue};
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
@@ -4403,6 +4402,8 @@ impl Machine {
|
|||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn http_open(&mut self) -> CallResult {
|
pub(crate) fn http_open(&mut self) -> CallResult {
|
||||||
|
use tokio::task;
|
||||||
|
|
||||||
let address_sink = self.deref_register(1);
|
let address_sink = self.deref_register(1);
|
||||||
let method = read_heap_cell!(self.deref_register(3),
|
let method = read_heap_cell!(self.deref_register(3),
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
@@ -4466,7 +4467,7 @@ impl Machine {
|
|||||||
|
|
||||||
// do it!
|
// do it!
|
||||||
task::block_in_place(move || {
|
task::block_in_place(move || {
|
||||||
match Handle::current().block_on(req.send()) {
|
match tokio::runtime::Handle::current().block_on(req.send()) {
|
||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
// status code
|
// status code
|
||||||
let status = resp.status().as_u16();
|
let status = resp.status().as_u16();
|
||||||
@@ -7843,22 +7844,33 @@ impl Machine {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn crypto_random_byte(&mut self) {
|
pub(crate) fn crypto_random_byte(&mut self) {
|
||||||
let arg = self.machine_st.registers[1];
|
#[cfg(feature = "crypto-full")]
|
||||||
let mut bytes: [u8; 1] = [0];
|
{
|
||||||
|
let arg = self.machine_st.registers[1];
|
||||||
|
let mut bytes: [u8; 1] = [0];
|
||||||
|
|
||||||
match rng().fill(&mut bytes) {
|
match rng().fill(&mut bytes) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// the error payload here is of type 'Unspecified',
|
// the error payload here is of type 'Unspecified',
|
||||||
// which contains no information whatsoever. So, for now,
|
// which contains no information whatsoever. So, for now,
|
||||||
// just fail.
|
// just fail.
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let byte = Fixnum::build_with(bytes[0]);
|
||||||
|
self.machine_st.unify_fixnum(byte, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let byte = Fixnum::build_with(bytes[0]);
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
self.machine_st.unify_fixnum(byte, arg);
|
{
|
||||||
|
let stub_gen = || functor_stub(atom!("crypto_random_byte"), 1);
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -7990,29 +8002,40 @@ impl Machine {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let ints = digest::digest(
|
#[cfg(feature = "crypto-full")]
|
||||||
match algorithm {
|
{
|
||||||
atom!("sha256") => &digest::SHA256,
|
let ints = digest::digest(
|
||||||
atom!("sha384") => &digest::SHA384,
|
match algorithm {
|
||||||
atom!("sha512") => &digest::SHA512,
|
atom!("sha256") => &digest::SHA256,
|
||||||
atom!("sha512_256") => &digest::SHA512_256,
|
atom!("sha384") => &digest::SHA384,
|
||||||
_ => {
|
atom!("sha512") => &digest::SHA512,
|
||||||
unreachable!()
|
atom!("sha512_256") => &digest::SHA512_256,
|
||||||
}
|
_ => {
|
||||||
},
|
unreachable!()
|
||||||
&bytes,
|
}
|
||||||
);
|
},
|
||||||
|
&bytes,
|
||||||
|
);
|
||||||
|
|
||||||
step_or_resource_error!(
|
step_or_resource_error!(
|
||||||
self.machine_st,
|
self.machine_st,
|
||||||
sized_iter_to_heap_list(
|
sized_iter_to_heap_list(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
ints.as_ref().len(),
|
ints.as_ref().len(),
|
||||||
ints.as_ref()
|
ints.as_ref()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
|
{
|
||||||
|
let stub_gen = || functor_stub(atom!("crypto_data_hash"), 1);
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -8021,168 +8044,201 @@ impl Machine {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn crypto_hmac(&mut self) {
|
pub(crate) fn crypto_hmac(&mut self) {
|
||||||
let encoding = cell_as_atom!(self.deref_register(2));
|
|
||||||
let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
|
|
||||||
|
|
||||||
let stub_gen = || functor_stub(atom!("crypto_data_hash"), 3);
|
let stub_gen = || functor_stub(atom!("crypto_data_hash"), 3);
|
||||||
|
|
||||||
let key = self
|
#[cfg(feature = "crypto-full")]
|
||||||
.machine_st
|
{
|
||||||
.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
|
let encoding = cell_as_atom!(self.deref_register(2));
|
||||||
|
let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
|
||||||
|
|
||||||
let algorithm = cell_as_atom!(self.deref_register(5));
|
let key = self
|
||||||
let ralg = match algorithm {
|
.machine_st
|
||||||
atom!("sha256") => hmac::HMAC_SHA256,
|
.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
|
||||||
atom!("sha384") => hmac::HMAC_SHA384,
|
|
||||||
atom!("sha512") => hmac::HMAC_SHA512,
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let rkey = hmac::Key::new(ralg, key.as_ref());
|
let algorithm = cell_as_atom!(self.deref_register(5));
|
||||||
let tag = hmac::sign(&rkey, &data);
|
let ralg = match algorithm {
|
||||||
|
atom!("sha256") => hmac::HMAC_SHA256,
|
||||||
|
atom!("sha384") => hmac::HMAC_SHA384,
|
||||||
|
atom!("sha512") => hmac::HMAC_SHA512,
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let ints_list = step_or_resource_error!(
|
let rkey = hmac::Key::new(ralg, key.as_ref());
|
||||||
self.machine_st,
|
let tag = hmac::sign(&rkey, &data);
|
||||||
sized_iter_to_heap_list(
|
|
||||||
&mut self.machine_st.heap,
|
|
||||||
tag.as_ref().len(),
|
|
||||||
tag.as_ref()
|
|
||||||
.iter()
|
|
||||||
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
|
let ints_list = step_or_resource_error!(
|
||||||
|
self.machine_st,
|
||||||
|
sized_iter_to_heap_list(
|
||||||
|
&mut self.machine_st.heap,
|
||||||
|
tag.as_ref().len(),
|
||||||
|
tag.as_ref()
|
||||||
|
.iter()
|
||||||
|
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn crypto_data_hkdf(&mut self) {
|
pub(crate) fn crypto_data_hkdf(&mut self) {
|
||||||
let encoding = cell_as_atom!(self.deref_register(2));
|
|
||||||
let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
|
|
||||||
|
|
||||||
let stub1_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
|
let stub1_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
|
||||||
let salt = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[3], stub1_gen);
|
|
||||||
|
|
||||||
let stub2_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
|
#[cfg(feature = "crypto-full")]
|
||||||
let info = self
|
{
|
||||||
.machine_st
|
let encoding = cell_as_atom!(self.deref_register(2));
|
||||||
.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
|
let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
|
||||||
|
|
||||||
let algorithm = cell_as_atom!(self.deref_register(5));
|
let salt = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[3], stub1_gen);
|
||||||
|
|
||||||
let length = self.deref_register(6);
|
let stub2_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
|
||||||
|
let info = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
|
||||||
|
|
||||||
let length = match Number::try_from((length, &self.machine_st.arena.f64_tbl)) {
|
let algorithm = cell_as_atom!(self.deref_register(5));
|
||||||
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(),
|
|
||||||
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
|
let length = self.deref_register(6);
|
||||||
Ok(u) => u,
|
|
||||||
|
let length = match Number::try_from((length, &self.machine_st.arena.f64_tbl)) {
|
||||||
|
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(),
|
||||||
|
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
|
||||||
|
Ok(u) => u,
|
||||||
|
_ => {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
self.machine_st.fail = true;
|
unreachable!()
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let ints_list = {
|
|
||||||
let digest_alg = match algorithm {
|
|
||||||
atom!("sha256") => hkdf::HKDF_SHA256,
|
|
||||||
atom!("sha384") => hkdf::HKDF_SHA384,
|
|
||||||
atom!("sha512") => hkdf::HKDF_SHA512,
|
|
||||||
_ => {
|
|
||||||
self.machine_st.fail = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let salt = hkdf::Salt::new(digest_alg, &salt);
|
let ints_list = {
|
||||||
let mut bytes: Vec<u8> = vec![0; length];
|
let digest_alg = match algorithm {
|
||||||
|
atom!("sha256") => hkdf::HKDF_SHA256,
|
||||||
|
atom!("sha384") => hkdf::HKDF_SHA384,
|
||||||
|
atom!("sha512") => hkdf::HKDF_SHA512,
|
||||||
|
_ => {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match salt.extract(&data).expand(&[&info[..]], MyKey(length)) {
|
let salt = hkdf::Salt::new(digest_alg, &salt);
|
||||||
Ok(r) => {
|
let mut bytes: Vec<u8> = vec![0; length];
|
||||||
r.fill(&mut bytes).unwrap();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.machine_st.fail = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
step_or_resource_error!(
|
match salt.extract(&data).expand(&[&info[..]], MyKey(length)) {
|
||||||
self.machine_st,
|
Ok(r) => {
|
||||||
sized_iter_to_heap_list(
|
r.fill(&mut bytes).unwrap();
|
||||||
&mut self.machine_st.heap,
|
}
|
||||||
bytes.len(),
|
|
||||||
bytes
|
|
||||||
.iter()
|
|
||||||
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[7], ints_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn crypto_password_hash(&mut self) {
|
|
||||||
let stub1_gen = || functor_stub(atom!("crypto_password_hash"), 3);
|
|
||||||
let data = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[1], stub1_gen);
|
|
||||||
let stub2_gen = || functor_stub(atom!("crypto_password_hash"), 3);
|
|
||||||
let salt = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[2], stub2_gen);
|
|
||||||
|
|
||||||
let iterations = self.deref_register(3);
|
|
||||||
|
|
||||||
let iterations = match Number::try_from((iterations, &self.machine_st.arena.f64_tbl)) {
|
|
||||||
Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(),
|
|
||||||
Ok(Number::Integer(n)) => {
|
|
||||||
let n: Result<u64, _> = (&*n).try_into();
|
|
||||||
match n {
|
|
||||||
Ok(i) => i,
|
|
||||||
_ => {
|
_ => {
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let ints_list = {
|
step_or_resource_error!(
|
||||||
let mut bytes = [0u8; digest::SHA512_OUTPUT_LEN];
|
self.machine_st,
|
||||||
|
sized_iter_to_heap_list(
|
||||||
pbkdf2::derive(
|
&mut self.machine_st.heap,
|
||||||
pbkdf2::PBKDF2_HMAC_SHA512,
|
bytes.len(),
|
||||||
NonZeroU32::new(iterations as u32).unwrap(),
|
bytes
|
||||||
&salt,
|
.iter()
|
||||||
&data,
|
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
||||||
&mut bytes,
|
)
|
||||||
);
|
|
||||||
|
|
||||||
step_or_resource_error!(
|
|
||||||
self.machine_st,
|
|
||||||
sized_iter_to_heap_list(
|
|
||||||
&mut self.machine_st.heap,
|
|
||||||
bytes.len(),
|
|
||||||
bytes
|
|
||||||
.iter()
|
|
||||||
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
|
||||||
)
|
)
|
||||||
)
|
};
|
||||||
};
|
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
|
unify!(self.machine_st, self.machine_st.registers[7], ints_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub1_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn crypto_password_hash(&mut self) {
|
||||||
|
let stub1_gen = || functor_stub(atom!("crypto_password_hash"), 3);
|
||||||
|
|
||||||
|
#[cfg(feature = "crypto-full")]
|
||||||
|
{
|
||||||
|
use std::num::NonZeroU32;
|
||||||
|
let data = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[1], stub1_gen);
|
||||||
|
let stub2_gen = || functor_stub(atom!("crypto_password_hash"), 3);
|
||||||
|
let salt = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[2], stub2_gen);
|
||||||
|
|
||||||
|
let iterations = self.deref_register(3);
|
||||||
|
|
||||||
|
let iterations = match Number::try_from((iterations, &self.machine_st.arena.f64_tbl)) {
|
||||||
|
Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(),
|
||||||
|
Ok(Number::Integer(n)) => {
|
||||||
|
let n: Result<u64, _> = (&*n).try_into();
|
||||||
|
match n {
|
||||||
|
Ok(i) => i,
|
||||||
|
_ => {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let ints_list = {
|
||||||
|
let mut bytes = [0u8; digest::SHA512_OUTPUT_LEN];
|
||||||
|
|
||||||
|
pbkdf2::derive(
|
||||||
|
pbkdf2::PBKDF2_HMAC_SHA512,
|
||||||
|
NonZeroU32::new(iterations as u32).unwrap(),
|
||||||
|
&salt,
|
||||||
|
&data,
|
||||||
|
&mut bytes,
|
||||||
|
);
|
||||||
|
|
||||||
|
step_or_resource_error!(
|
||||||
|
self.machine_st,
|
||||||
|
sized_iter_to_heap_list(
|
||||||
|
&mut self.machine_st.heap,
|
||||||
|
bytes.len(),
|
||||||
|
bytes
|
||||||
|
.iter()
|
||||||
|
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub1_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "crypto-full")]
|
#[cfg(feature = "crypto-full")]
|
||||||
@@ -8304,109 +8360,153 @@ impl Machine {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn crypto_curve_scalar_mult(&mut self) {
|
pub(crate) fn crypto_curve_scalar_mult(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("crypto_curve_scalar_mult"), 4);
|
let stub_gen = || functor_stub(atom!("crypto_curve_scalar_mult"), 4);
|
||||||
let scalar_bytes = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[2], stub_gen);
|
|
||||||
let point_bytes = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
|
|
||||||
|
|
||||||
let mut point = secp256k1::Point::decode(&point_bytes).unwrap();
|
{
|
||||||
let scalar = secp256k1::Scalar::decode_reduce(&scalar_bytes);
|
let scalar_bytes = self
|
||||||
point *= scalar;
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[2], stub_gen);
|
||||||
|
let point_bytes = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
|
||||||
|
|
||||||
let uncompressed = step_or_resource_error!(
|
let mut point = secp256k1::Point::decode(&point_bytes).unwrap();
|
||||||
self.machine_st,
|
let scalar = secp256k1::Scalar::decode_reduce(&scalar_bytes);
|
||||||
self.u8s_to_string(&point.encode_uncompressed())
|
point *= scalar;
|
||||||
);
|
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
|
let uncompressed = step_or_resource_error!(
|
||||||
|
self.machine_st,
|
||||||
|
self.u8s_to_string(&point.encode_uncompressed())
|
||||||
|
);
|
||||||
|
|
||||||
|
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn ed25519_seed_to_public_key(&mut self) {
|
pub(crate) fn ed25519_seed_to_public_key(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("ed25519_seed_keypair"), 2);
|
let stub_gen = || functor_stub(atom!("ed25519_seed_keypair"), 2);
|
||||||
let seed_bytes = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
|
||||||
|
|
||||||
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
{
|
||||||
|
let seed_bytes = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||||
|
|
||||||
let complete_string = step_or_resource_error!(
|
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
||||||
self.machine_st,
|
|
||||||
self.u8s_to_string(skey.public_key.encoded.as_ref())
|
|
||||||
);
|
|
||||||
|
|
||||||
unify!(
|
let complete_string = step_or_resource_error!(
|
||||||
self.machine_st,
|
self.machine_st,
|
||||||
self.machine_st.registers[2],
|
self.u8s_to_string(skey.public_key.encoded.as_ref())
|
||||||
complete_string
|
);
|
||||||
);
|
|
||||||
|
unify!(
|
||||||
|
self.machine_st,
|
||||||
|
self.machine_st.registers[2],
|
||||||
|
complete_string
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn ed25519_sign_raw(&mut self) {
|
pub(crate) fn ed25519_sign_raw(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("ed25519_sign"), 4);
|
let stub_gen = || functor_stub(atom!("ed25519_sign"), 4);
|
||||||
let seed_bytes = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
|
||||||
|
|
||||||
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
{
|
||||||
|
let seed_bytes = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||||
|
|
||||||
let encoding = cell_as_atom!(self.deref_register(3));
|
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
||||||
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
|
||||||
|
|
||||||
let sig = skey.sign_raw(&data);
|
let encoding = cell_as_atom!(self.deref_register(3));
|
||||||
let sig_list = step_or_resource_error!(
|
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
||||||
self.machine_st,
|
|
||||||
sized_iter_to_heap_list(
|
|
||||||
&mut self.machine_st.heap,
|
|
||||||
sig.as_ref().len(),
|
|
||||||
sig.as_ref()
|
|
||||||
.iter()
|
|
||||||
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
|
let sig = skey.sign_raw(&data);
|
||||||
|
let sig_list = step_or_resource_error!(
|
||||||
|
self.machine_st,
|
||||||
|
sized_iter_to_heap_list(
|
||||||
|
&mut self.machine_st.heap,
|
||||||
|
sig.as_ref().len(),
|
||||||
|
sig.as_ref()
|
||||||
|
.iter()
|
||||||
|
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn ed25519_verify_raw(&mut self) {
|
pub(crate) fn ed25519_verify_raw(&mut self) {
|
||||||
let key_bytes = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
|
|
||||||
let pkey = ed25519::PublicKey::decode(&key_bytes).unwrap();
|
|
||||||
|
|
||||||
let encoding = cell_as_atom!(self.deref_register(3));
|
|
||||||
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
|
||||||
|
|
||||||
let stub_gen = || functor_stub(atom!("ed25519_verify"), 4);
|
let stub_gen = || functor_stub(atom!("ed25519_verify"), 4);
|
||||||
|
|
||||||
let signature = self
|
{
|
||||||
.machine_st
|
let key_bytes =
|
||||||
.integers_to_bytevec(self.machine_st.registers[4], stub_gen);
|
self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
|
||||||
|
let pkey = ed25519::PublicKey::decode(&key_bytes).unwrap();
|
||||||
|
|
||||||
self.machine_st.fail = !pkey.verify_raw(&signature, &data);
|
let encoding = cell_as_atom!(self.deref_register(3));
|
||||||
|
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
||||||
|
|
||||||
|
let signature = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[4], stub_gen);
|
||||||
|
|
||||||
|
self.machine_st.fail = !pkey.verify_raw(&signature, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn curve25519_scalar_mult(&mut self) {
|
pub(crate) fn curve25519_scalar_mult(&mut self) {
|
||||||
let stub1_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
|
let stub_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
|
||||||
let scalar_bytes = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[1], stub1_gen);
|
|
||||||
let stub2_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
|
|
||||||
let point_bytes = self
|
|
||||||
.machine_st
|
|
||||||
.integers_to_bytevec(self.machine_st.registers[2], stub2_gen);
|
|
||||||
|
|
||||||
let result = x25519::x25519(
|
{
|
||||||
&<[u8; 32]>::try_from(&point_bytes[..]).unwrap(),
|
let scalar_bytes = self
|
||||||
&<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap(),
|
.machine_st
|
||||||
);
|
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||||
|
let point_bytes = self
|
||||||
|
.machine_st
|
||||||
|
.integers_to_bytevec(self.machine_st.registers[2], stub_gen);
|
||||||
|
|
||||||
let string = step_or_resource_error!(self.machine_st, self.u8s_to_string(&result[..]));
|
let result = x25519::x25519(
|
||||||
|
&<[u8; 32]>::try_from(&point_bytes[..]).unwrap(),
|
||||||
|
&<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[3], string);
|
let string = step_or_resource_error!(self.machine_st, self.u8s_to_string(&result[..]));
|
||||||
|
|
||||||
|
unify!(self.machine_st, self.machine_st.registers[3], string);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
||||||
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
|
self.machine_st.throw_exception(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -8848,36 +8948,27 @@ impl Machine {
|
|||||||
Some(atom!("std")) => Stdio::inherit(),
|
Some(atom!("std")) => Stdio::inherit(),
|
||||||
Some(atom!("null")) => Stdio::null(),
|
Some(atom!("null")) => Stdio::null(),
|
||||||
Some(atom!("pipe")) => {
|
Some(atom!("pipe")) => {
|
||||||
#[cfg(rust_version = "1.87.0")]
|
let (reader, writer) = match std::io::pipe() {
|
||||||
#[allow(clippy::incompatible_msrv)]
|
Ok(pipe_pair) => pipe_pair,
|
||||||
{
|
Err(_) => {
|
||||||
let (reader, writer) = match std::io::pipe() {
|
return Err(self.machine_st.open_permission_error(
|
||||||
Ok(pipe_pair) => pipe_pair,
|
atom!("anonymous_pipe"),
|
||||||
Err(_) => {
|
atom!("process_create"),
|
||||||
return Err(self.machine_st.open_permission_error(
|
3,
|
||||||
atom!("anonymous_pipe"),
|
));
|
||||||
atom!("process_create"),
|
}
|
||||||
3,
|
};
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let stream = Stream::from_pipe_writer(writer, &mut self.machine_st.arena);
|
let stream = Stream::from_pipe_writer(writer, &mut self.machine_st.arena);
|
||||||
|
|
||||||
self.indices
|
self.indices
|
||||||
.add_stream(stream, atom!("process_create"), 3)
|
.add_stream(stream, atom!("process_create"), 3)
|
||||||
.map_err(|stub_gen| stub_gen(&mut self.machine_st))?;
|
.map_err(|stub_gen| stub_gen(&mut self.machine_st))?;
|
||||||
|
|
||||||
self.machine_st
|
self.machine_st
|
||||||
.bind(args[1].as_var().unwrap(), stream.into());
|
.bind(args[1].as_var().unwrap(), stream.into());
|
||||||
|
|
||||||
Stdio::from(reader)
|
Stdio::from(reader)
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(rust_version = "1.87.0"))]
|
|
||||||
{
|
|
||||||
Stdio::piped()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Some(atom!("file")) => {
|
Some(atom!("file")) => {
|
||||||
let path = self.machine_st.value_to_str_like(args[1]).unwrap();
|
let path = self.machine_st.value_to_str_like(args[1]).unwrap();
|
||||||
@@ -9509,6 +9600,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "crypto-full")]
|
||||||
fn rng() -> &'static dyn SecureRandom {
|
fn rng() -> &'static dyn SecureRandom {
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
@@ -9517,8 +9609,10 @@ fn rng() -> &'static dyn SecureRandom {
|
|||||||
RANDOM.deref()
|
RANDOM.deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "crypto-full")]
|
||||||
struct MyKey<T: core::fmt::Debug + PartialEq>(T);
|
struct MyKey<T: core::fmt::Debug + PartialEq>(T);
|
||||||
|
|
||||||
|
#[cfg(feature = "crypto-full")]
|
||||||
impl hkdf::KeyType for MyKey<usize> {
|
impl hkdf::KeyType for MyKey<usize> {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.0
|
self.0
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::helper::load_module_test;
|
use crate::helper::load_module_test;
|
||||||
use crate::helper::load_module_test_with_input;
|
use crate::helper::load_module_test_with_input;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(all(feature = "http", not(target_arch = "wasm32")))]
|
||||||
use crate::helper::load_module_test_with_tokio_runtime_and_input;
|
use crate::helper::load_module_test_with_tokio_runtime_and_input;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
@@ -164,8 +164,7 @@ fn issue3262_read_from_stdin_no_newline() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "http")]
|
#[cfg(all(feature = "http", not(target_arch = "wasm32")))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
#[cfg_attr(miri, ignore = "it takes too long to run")]
|
#[cfg_attr(miri, ignore = "it takes too long to run")]
|
||||||
fn http_open_hanging() {
|
fn http_open_hanging() {
|
||||||
load_module_test_with_tokio_runtime_and_input(
|
load_module_test_with_tokio_runtime_and_input(
|
||||||
|
|||||||
Reference in New Issue
Block a user