Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

x509-cert/const-oid: a 100-character OID (RFC 5280 Appendix B) needs 40 octets, so a certificate carrying one as a non-critical extension id does not decode

オープン
#2,485 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

  • #2497 @choksi2212 による — マージされずにクローズ

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
45/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
rust
領域
backend, security

調査の方向性

Start with const-oid’s DEFAULT_MAX_SIZE and parsing in src/lib.rs and src/encoder.rs, then trace DER OID decoding in der/src/asn1/oid.rs and Extension::extn_id in x509-cert’s src/ext.rs. Reproduce the 40-octet case and compare it with the 39-octet control. Done when certificates with the Appendix B sized non-critical extension OID decode successfully and the existing controls still pass.

索引モデルが issue の本文から書いたものです。

説明

Hi,

RFC 5280 Appendix B requires support for OIDs whose dotted-decimal form is up to 100 characters, with up to 20 arcs, each below 2^28. ObjectIdentifier's default capacity is 39 octets. A 100-character OID that stays within those limits can need 40, and then it doesn't fit. When that OID is the id of a non-critical extension, Certificate::from_der refuses the whole certificate, although RFC 5280 §4.2 says a non-critical extension a relying party doesn't recognise MAY be ignored.

The OID used is 1.3 followed by nine arcs of 268435455 (2^28 − 1, the largest Appendix B mandates) and then 123456: 12 arcs, 100 characters, 40 contents octets (1 + 9 × 4 + 3). The control swaps the last arc for 16383 (99 characters, 39 octets) and decodes fine. The three test certificates differ only in that extension id, and both controls re-encode to the exact octets they were decoded from, so the DER is canonical and the 40th octet is what fails.

What the reproduction shows

const-oid 0.10.2 + x509-cert 0.3.0 const-oid 0.9.6 + x509-cert 0.2.5
OID, 100 chars / 40 octets new and from_bytes: Err(Length) from_bytes: Err(NotEnoughArcs)
OID, 99 chars / 39 octets (control) Ok Ok
certificate, extension id 1.3.6.1.4.1.99999.1 (control) Ok, re-encodes identically Ok, re-encodes identically
certificate, extension id = the 99-char OID (control) Ok, re-encodes identically Ok, re-encodes identically
certificate, extension id = the 100-char OID Err: incorrect length for OBJECT IDENTIFIER at DER byte 214 Err: incorrect length for OBJECT IDENTIFIER at DER byte 212

Where it comes from

  • const-oid 0.10.2: DEFAULT_MAX_SIZE is 39 (src/lib.rs:48, src/lib.rs:66). The string parser refuses an arc that would end past it (src/encoder.rs:96-102), and from_bytes does the same after checking the arcs (src/lib.rs:121-132 into src/lib.rs:234-254, Error::Length at :240-241).
  • der 0.8.2 decodes an OBJECT IDENTIFIER into a buffer of that capacity and fails when the contents are longer (src/asn1/oid.rs:12-28).
  • x509-cert 0.3.0 and 0.2.5 type Extension::extn_id as the default ObjectIdentifier (src/ext.rs:29-36), and the extensions are a field of the TBS certificate (src/certificate.rs:163-164 in 0.3.0), so one extension id that doesn't fit fails the decode, critical or not.
  • On 0.9.6, from_bytes reports an input that is too long as Error::NotEnoughArcs (src/lib.rs:143-147), which names the wrong problem.
flowchart TD
  cert["Certificate DER, extension id = 1.3 + 9 x 268435455 + 123456<br/>100 characters, 40 octets (RFC 5280 App. B: must be supported)"]
  cert --> a["x509-cert 0.3.0 Certificate::from_der"]
  cert --> b["x509-cert 0.2.5 Certificate::from_der"]
  a --> ext3["Extension.extn_id: ObjectIdentifier<br/>ext.rs:29-36"]
  b --> ext2["Extension.extn_id: ObjectIdentifier<br/>ext.rs:29-36"]
  ext3 --> d8["der 0.8.2 decode_value: buf [u8; 39]<br/>oid.rs:12-28 -> length error"]
  ext2 --> d7["der 0.7.10 decode_value: buf [u8; 39]<br/>oid.rs:12-23 -> length error"]
  d8 --> cap10["const-oid 0.10.2 DEFAULT_MAX_SIZE = 39<br/>lib.rs:48, 66"]
  d7 --> cap9["const-oid 0.9.6 MAX_SIZE = 39<br/>lib.rs:92"]
  cap10 --> fail["Err: the whole certificate is unreadable<br/>(RFC 5280 4.2: a non-critical extension MAY be ignored)"]
  cap9 --> fail
  ctl["control: the same certificate with 39 octets<br/>Ok, re-encodes identically"]
  classDef bad fill:#fde,stroke:#b35
  classDef good fill:#def,stroke:#37b
  class fail bad
  class ctl good

This is related to #1984 but isn't the same thing: that asked for arcs beyond 2^32, which Appendix B doesn't require. This OID is inside Appendix B's limits and is one octet over the default capacity.

What would help, if you agree it's worth fixing: a default capacity that holds every OID Appendix B mandates, or an x509-cert decode path that accepts a larger MAX_SIZE, which const-oid's const parameter already makes possible. I'm happy to send a PR for whichever you prefer.

Reproduction script (self-contained; needs bash, rustup and network access for cargo to fetch the pinned crates)

Save it as repro.sh and run bash repro.sh. It writes a small Cargo project (locked by its own Cargo.lock) into a new temporary directory, builds it with Rust 1.98.0, and compares each observation with the table above. It exits 0 when everything matches. The script is yours to use under Apache-2.0 OR MIT.

#!/usr/bin/env bash
# SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
# Self-contained reproduction (UP-CONSTOID-001). It writes the files below into a new
# temporary directory and runs repro.sh there; nothing outside that
# directory is written. Run it with: bash this-file.sh
set -euo pipefail
dir=$(mktemp -d "${TMPDIR:-/tmp}/repro.XXXXXX")
echo "files written to $dir"
cat >"$dir/rust-toolchain.toml" <<'__REPRO_FILE_1__'
[toolchain]
channel = "1.98.0"
__REPRO_FILE_1__
mkdir -p "$dir/harness"
cat >"$dir/harness/Cargo.lock" <<'__REPRO_FILE_2__'
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4

[[package]]
name = "base64ct"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"

[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"

[[package]]
name = "const-oid"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"

[[package]]
name = "der"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
 "const-oid 0.9.6",
 "der_derive 0.7.3",
 "flagset",
 "zeroize",
]

[[package]]
name = "der"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a878c850e9e421b20262e9b41f9c860e4785fa07541c266b62ff9d1ef998a80a"
dependencies = [
 "const-oid 0.10.2",
 "der_derive 0.8.0",
 "flagset",
 "zeroize",
]

[[package]]
name = "der_derive"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "der_derive"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59600e2c2d636fde9b65e99cc6445ac770c63d3628195ff39932b8d6d7409903"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "flagset"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe"

[[package]]
name = "proc-macro2"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
 "unicode-ident",
]

[[package]]
name = "quote"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
 "proc-macro2",
]

[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
 "base64ct",
 "der 0.7.10",
]

[[package]]
name = "spki"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9"
dependencies = [
 "base64ct",
 "der 0.8.2",
]

[[package]]
name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
 "proc-macro2",
 "quote",
 "unicode-ident",
]

[[package]]
name = "unicode-ident"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"

[[package]]
name = "up-constoid-001"
version = "0.0.0"
dependencies = [
 "const-oid 0.10.2",
 "const-oid 0.9.6",
 "x509-cert 0.2.5",
 "x509-cert 0.3.0",
]

[[package]]
name = "x509-cert"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94"
dependencies = [
 "const-oid 0.9.6",
 "der 0.7.10",
 "spki 0.7.3",
]

[[package]]
name = "x509-cert"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "105ef4642d9cb137ef83d623d0e4bf08b8adf69e9918ca904a174adb6d3d038b"
dependencies = [
 "const-oid 0.10.2",
 "der 0.8.2",
 "spki 0.8.1",
]

[[package]]
name = "zeroize"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879"
__REPRO_FILE_2__
mkdir -p "$dir/harness"
cat >"$dir/harness/Cargo.toml" <<'__REPRO_FILE_3__'
# SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
# SPDX-License-Identifier: Apache-2.0 OR MIT
#

# UP-CONSTOID-001's harness: const-oid 0.10.2 under x509-cert 0.3.0 (the
# newest of each), and const-oid 0.9.6 under x509-cert 0.2.5 (the 0.2
# line).
[package]
name = "up-constoid-001"
version = "0.0.0"
edition = "2021"
publish = false

[dependencies]
const-oid = "=0.10.2"
x509-cert = { version = "=0.3.0", default-features = false }
const-oid-09 = { package = "const-oid", version = "=0.9.6" }
x509-cert-02 = { package = "x509-cert", version = "=0.2.5", default-features = false }

[workspace]
__REPRO_FILE_3__
mkdir -p "$dir/harness/src"
cat >"$dir/harness/src/main.rs" <<'__REPRO_FILE_4__'
// SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
// SPDX-License-Identifier: Apache-2.0 OR MIT
//

//! UP-CONSTOID-001: an OID whose dotted-decimal form is 100 characters, as
//! the id of a non-critical extension, through const-oid 0.10.2 / x509-cert
//! 0.3.0 and const-oid 0.9.6 / x509-cert 0.2.5. RFC 5280 Appendix B:
//! "Implementations MUST also support OIDs where the length of the dotted
//! decimal ... string representation can be up to 100 bytes (inclusive)."
//! The certificate is assembled here octet by octet, so nothing of either
//! crate builds it; the control decodes and re-encodes to the same octets.
//! Prints `OBS key=value`.

use x509_cert::der::{Decode as _, Encode as _};
use x509_cert_02::der::{Decode as _, Encode as _};

/// The dotted form: `1.3`, nine `.268435455` (2^28 - 1, the largest arc RFC
/// 5280 Appendix B mandates) and a last arc.
fn dotted(last: u32) -> String {
    let mut s = String::from("1.3");
    for _ in 0..9 {
        s.push_str(".268435455");
    }
    s.push_str(&format!(".{last}"));
    s
}

/// X.690 §8.19 contents octets, written here rather than by either crate.
fn oid_contents(dotted: &str) -> Vec<u8> {
    let arcs: Vec<u64> = dotted.split('.').map(|a| a.parse().expect("digits")).collect();
    let mut out = vec![(arcs[0] * 40 + arcs[1]) as u8];
    for &arc in &arcs[2..] {
        let mut groups = vec![(arc & 0x7f) as u8];
        let mut rest = arc >> 7;
        while rest > 0 {
            groups.push(0x80 | (rest & 0x7f) as u8);
            rest >>= 7;
        }
        groups.reverse();
        out.extend(groups);
    }
    out
}

fn tlv(tag: u8, value: &[u8]) -> Vec<u8> {
    let mut out = vec![tag];
    let n = value.len();
    if n < 0x80 {
        out.push(n as u8);
    } else if n <= 0xff {
        out.extend([0x81, n as u8]);
    } else {
        out.extend([0x82, (n >> 8) as u8, n as u8]);
    }
    out.extend_from_slice(value);
    out
}

fn seq(parts: &[Vec<u8>]) -> Vec<u8> {
    tlv(0x30, &parts.concat())
}

fn oid(dotted: &str) -> Vec<u8> {
    tlv(0x06, &oid_contents(dotted))
}

/// A v3 certificate with one non-critical extension whose id is `ext_id`.
fn certificate(ext_id: &str) -> Vec<u8> {
    let ecdsa_sha256 = seq(&[oid("1.2.840.10045.4.3.2")]);
    let name = seq(&[tlv(0x31, &seq(&[oid("2.5.4.3"), tlv(0x0c, b"up-constoid-001")]))]);
    let validity = seq(&[tlv(0x17, b"250101000000Z"), tlv(0x17, b"350101000000Z")]);
    let mut point = vec![0x00, 0x04];
    point.extend([0x11; 64]);
    let spki = seq(&[
        seq(&[oid("1.2.840.10045.2.1"), oid("1.2.840.10045.3.1.7")]),
        tlv(0x03, &point),
    ]);
    let extension = seq(&[oid(ext_id), tlv(0x04, &[0x05, 0x00])]);
    let tbs = seq(&[
        tlv(0xa0, &tlv(0x02, &[0x02])),
        tlv(0x02, &[0x01]),
        ecdsa_sha256.clone(),
        name.clone(),
        validity,
        name,
        spki,
        tlv(0xa3, &seq(&[extension])),
    ]);
    seq(&[tbs, ecdsa_sha256, tlv(0x03, &[0x00, 0x01, 0x02, 0x03])])
}

fn obs(key: &str, value: impl std::fmt::Display) {
    println!("OBS {key}={value}");
}

fn verdict<T, E: std::fmt::Debug>(r: &Result<T, E>) -> String {
    match r {
        Ok(_) => "Ok".to_owned(),
        Err(e) => format!("Err({e:?})"),
    }
}

/// Decode with both x509-cert lines; on Ok, say whether re-encoding gives
/// back the same octets (it proves the assembled DER is the canonical form).
fn decode_both(label: &str, der: &[u8]) {
    match x509_cert::Certificate::from_der(der) {
        Ok(cert) => {
            obs(&format!("{label}.x509-cert-0.3.0"), "Ok");
            obs(
                &format!("{label}.x509-cert-0.3.0.reencodes-identically"),
                cert.to_der().map(|d| d == der).unwrap_or(false),
            );
        }
        Err(e) => {
            obs(&format!("{label}.x509-cert-0.3.0"), "Err");
            obs(&format!("info.{label}.x509-cert-0.3.0.error"), e);
        }
    }
    match x509_cert_02::Certificate::from_der(der) {
        Ok(cert) => {
            obs(&format!("{label}.x509-cert-0.2.5"), "Ok");
            obs(
                &format!("{label}.x509-cert-0.2.5.reencodes-identically"),
                cert.to_der().map(|d| d == der).unwrap_or(false),
            );
        }
        Err(e) => {
            obs(&format!("{label}.x509-cert-0.2.5"), "Err");
            obs(&format!("info.{label}.x509-cert-0.2.5.error"), e);
        }
    }
}

fn main() {
    // 100 characters, 40 BER octets: the claim.
    let long = dotted(123456);
    // 99 characters, 39 BER octets: the largest the crates hold.
    let fits = dotted(16383);

    obs("oid100.chars", long.len());
    obs("oid100.ber-octets", oid_contents(&long).len());
    obs("oid99.chars", fits.len());
    obs("oid99.ber-octets", oid_contents(&fits).len());

    obs("const-oid-0.10.2.new(oid100)", verdict(&const_oid::ObjectIdentifier::new(&long)));
    obs(
        "const-oid-0.10.2.from_bytes(oid100)",
        verdict(&const_oid::ObjectIdentifier::from_bytes(&oid_contents(&long))),
    );
    obs("const-oid-0.10.2.new(oid99)", verdict(&const_oid::ObjectIdentifier::new(&fits)));
    obs(
        "const-oid-0.9.6.from_bytes(oid100)",
        verdict(&const_oid_09::ObjectIdentifier::from_bytes(&oid_contents(&long))),
    );
    obs(
        "const-oid-0.9.6.from_bytes(oid99)",
        verdict(&const_oid_09::ObjectIdentifier::from_bytes(&oid_contents(&fits))),
    );
    obs("info.const-oid-0.9.6.new(oid100)", verdict(&const_oid_09::ObjectIdentifier::new(&long)));
    obs("info.const-oid-0.9.6.new(oid99)", verdict(&const_oid_09::ObjectIdentifier::new(&fits)));

    decode_both("control", &certificate("1.3.6.1.4.1.99999.1"));
    decode_both("cert-oid99", &certificate(&fits));
    decode_both("cert-oid100", &certificate(&long));
}
__REPRO_FILE_4__
cat >"$dir/repro.sh" <<'__REPRO_FILE_5__'
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
set -euo pipefail

# repro.sh — UP-CONSTOID-001: an OID whose dotted-decimal form is 100
# characters (RFC 5280 Appendix B: "MUST also support OIDs where the length
# of the dotted decimal ... string representation can be up to 100 bytes")
# does not fit const-oid's ObjectIdentifier, in 0.10.2 (the newest, under
# x509-cert 0.3.0) or 0.9.6 (under x509-cert 0.2.5); as the id of a
# non-critical extension it makes the whole certificate undecodable. A
# defensive check over a certificate the harness assembles octet by octet.
#
#   ./repro.sh
#
# What it does: builds harness/ (locked by harness/Cargo.lock) with the
# toolchain rust-toolchain.toml pins, runs it, and compares each
# `OBS key=value` with EXPECT, the claim table of the report. Lines named
# info.* are printed for the reader and not checked.
#
# Network: cargo's fetch of the crates harness/Cargo.lock pins. Nothing else.
#
# Exit status: 0 when every check holds (the defect is shown); otherwise the
# number of checks that disagreed; 2 if the harness could not be built or run.
#
# Dependencies: bash, awk, cargo and rustup (1.98.0).

here=$(cd "$(dirname "$0")" && pwd)
cd "$here"

fail=0
note() { echo "repro: $*"; }
check() {  # check <label> <want> <got>
  if [[ "$2" == "$3" ]]; then
    printf '  ok   %-60s %s\n' "$1" "$3"
  else
    printf '  FAIL %-60s got %s, want %s\n' "$1" "$3" "$2"
    fail=$((fail + 1))
  fi
}

if ! command -v cargo >/dev/null 2>&1; then
  note "cargo is not installed; cannot run"
  exit 2
fi
target=$(mktemp -d "${TMPDIR:-/tmp}/up-ev.XXXXXX")
trap 'rm -rf "$target"' EXIT

# The toolchain is the one the repository's rust-toolchain.toml pins.
rustc_version=$(cd "$here/harness" && rustc --version)
note "toolchain: $rustc_version"
check "rustc is the pinned 1.98.0" "rustc 1.98.0" "$(cut -d' ' -f1-2 <<<"$rustc_version")"

run_harness() {  # run_harness -> the harness's stdout
  (cd "$here/harness" && CARGO_TARGET_DIR="$target" cargo run --locked --quiet --release)
}

compare() {  # compare <label> <harness output> ; reads key=value lines on stdin
  local label="$1" out="$2" key want got
  while IFS='=' read -r key want; do
    [[ -z "$key" || "$key" == \#* ]] && continue
    got=$(awk -v k="OBS ${key}=" 'index($0, k) == 1 { print substr($0, length(k) + 1); exit }' <<<"$out")
    [[ -n "$got" ]] || got="(not printed)"
    check "$label: $key" "$want" "$got"
  done
}

finish() {  # finish <id>
  echo
  if [[ "$fail" -eq 0 ]]; then
    note "all checks held: $1 is shown as the report states it"
    exit 0
  fi
  note "$fail checks disagreed with the claim"
  exit "$fail"
}

note "building and running harness/ (const-oid 0.10.2 + x509-cert 0.3.0, const-oid 0.9.6 + x509-cert 0.2.5)"
out=$(run_harness) || { note "the harness did not build or run"; exit 2; }
printf '%s\n' "$out" | sed 's/^/    /'

compare oid "$out" <<'EXPECT'
oid100.chars=100
oid100.ber-octets=40
oid99.chars=99
oid99.ber-octets=39
EXPECT

compare const-oid "$out" <<'EXPECT'
const-oid-0.10.2.new(oid100)=Err(Length)
const-oid-0.10.2.from_bytes(oid100)=Err(Length)
const-oid-0.10.2.new(oid99)=Ok
const-oid-0.9.6.from_bytes(oid100)=Err(NotEnoughArcs)
const-oid-0.9.6.from_bytes(oid99)=Ok
EXPECT

# The controls: the assembled certificate is canonical DER, and the
# extension id is the only thing that changes between the three.
compare control "$out" <<'EXPECT'
control.x509-cert-0.3.0=Ok
control.x509-cert-0.3.0.reencodes-identically=true
control.x509-cert-0.2.5=Ok
control.x509-cert-0.2.5.reencodes-identically=true
cert-oid99.x509-cert-0.3.0=Ok
cert-oid99.x509-cert-0.3.0.reencodes-identically=true
cert-oid99.x509-cert-0.2.5=Ok
cert-oid99.x509-cert-0.2.5.reencodes-identically=true
EXPECT

compare claim "$out" <<'EXPECT'
cert-oid100.x509-cert-0.3.0=Err
cert-oid100.x509-cert-0.2.5=Err
EXPECT

finish UP-CONSTOID-001
__REPRO_FILE_5__
chmod +x "$dir/repro.sh"
cd "$dir" && ./repro.sh
Recorded run (macOS arm64, rustc 1.98.0)
repro: toolchain: rustc 1.98.0 (88d9e12ae 2026-08-18)
  ok   rustc is the pinned 1.98.0                                   rustc 1.98.0
repro: building and running harness/ (const-oid 0.10.2 + x509-cert 0.3.0, const-oid 0.9.6 + x509-cert 0.2.5)
  ok   oid: oid100.chars                                            100
  ok   oid: oid100.ber-octets                                       40
  ok   oid: oid99.chars                                             99
  ok   oid: oid99.ber-octets                                        39
  ok   const-oid: const-oid-0.10.2.new(oid100)                      Err(Length)
  ok   const-oid: const-oid-0.10.2.from_bytes(oid100)               Err(Length)
  ok   const-oid: const-oid-0.10.2.new(oid99)                       Ok
  ok   const-oid: const-oid-0.9.6.from_bytes(oid100)                Err(NotEnoughArcs)
  ok   const-oid: const-oid-0.9.6.from_bytes(oid99)                 Ok
  ok   control: control.x509-cert-0.3.0                             Ok
  ok   control: control.x509-cert-0.3.0.reencodes-identically       true
  ok   control: control.x509-cert-0.2.5                             Ok
  ok   control: control.x509-cert-0.2.5.reencodes-identically       true
  ok   control: cert-oid99.x509-cert-0.3.0                          Ok
  ok   control: cert-oid99.x509-cert-0.3.0.reencodes-identically    true
  ok   control: cert-oid99.x509-cert-0.2.5                          Ok
  ok   control: cert-oid99.x509-cert-0.2.5.reencodes-identically    true
  ok   claim: cert-oid100.x509-cert-0.3.0                           Err
  ok   claim: cert-oid100.x509-cert-0.2.5                           Err

repro: all checks held: UP-CONSTOID-001 is shown as the report states it
主要言語
Rust
スター
344
フォーク
196
平均マージ
1日 17時間
マージ済み PR(30日)
24

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

RustCrypto/formats のほかの issue

RustCrypto/formats の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。