1
Fork 0
mirror of https://github.com/RGBCube/cstree synced 2025-07-27 09:07:44 +00:00

Use strict provenance for pointer tagging (#36)

This commit is contained in:
DQ 2022-07-01 10:44:24 +02:00 committed by GitHub
parent f187aba06c
commit 2ffeb0e166
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 18 additions and 6 deletions

View file

@ -102,7 +102,7 @@ jobs:
rust-version: nightly rust-version: nightly
components: miri components: miri
env: env:
MIRIFLAGS: -Zmiri-disable-isolation MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance
- run: cargo miri test --verbose --all-features - run: cargo miri test --verbose --all-features
sanitizers: sanitizers:

View file

@ -22,6 +22,7 @@ parking_lot = "0.11.2"
# Arc # Arc
triomphe = "0.1.3" triomphe = "0.1.3"
sptr = "0.3.2"
[dependencies.serde] [dependencies.serde]
version = "1.0" version = "1.0"

View file

@ -4,6 +4,8 @@ use std::{fmt, hash, mem};
// This MUST be size=1 such that pointer math actually advances the pointer. // This MUST be size=1 such that pointer math actually advances the pointer.
type ErasedPtr = *const u8; type ErasedPtr = *const u8;
use sptr::Strict;
use crate::{ use crate::{
green::{GreenNode, GreenToken, SyntaxKind}, green::{GreenNode, GreenToken, SyntaxKind},
NodeOrToken, TextSize, NodeOrToken, TextSize,
@ -114,7 +116,7 @@ impl From<PackedGreenElement> for GreenElement {
impl PackedGreenElement { impl PackedGreenElement {
pub(crate) fn is_node(&self) -> bool { pub(crate) fn is_node(&self) -> bool {
self.ptr as usize & 1 == 0 self.ptr.addr() & super::token::IS_TOKEN_TAG == 0
} }
pub(crate) fn as_node(&self) -> Option<&GreenNode> { pub(crate) fn as_node(&self) -> Option<&GreenNode> {

View file

@ -5,6 +5,7 @@ use crate::{
interning::{Key, Resolver}, interning::{Key, Resolver},
TextSize, TextSize,
}; };
use sptr::Strict;
use triomphe::Arc; use triomphe::Arc;
#[repr(align(2))] // to use 1 bit for pointer tagging. NB: this is an at-least annotation #[repr(align(2))] // to use 1 bit for pointer tagging. NB: this is an at-least annotation
@ -23,17 +24,18 @@ pub struct GreenToken {
unsafe impl Send for GreenToken {} // where GreenTokenData: Send + Sync unsafe impl Send for GreenToken {} // where GreenTokenData: Send + Sync
unsafe impl Sync for GreenToken {} // where GreenTokenData: Send + Sync unsafe impl Sync for GreenToken {} // where GreenTokenData: Send + Sync
pub(super) const IS_TOKEN_TAG: usize = 0x1;
impl GreenToken { impl GreenToken {
fn add_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> { fn add_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
unsafe { unsafe {
let ptr = ((ptr.as_ptr() as usize) | 1) as *mut GreenTokenData; let ptr = ptr.as_ptr().map_addr(|addr| addr | IS_TOKEN_TAG);
ptr::NonNull::new_unchecked(ptr) ptr::NonNull::new_unchecked(ptr)
} }
} }
fn remove_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> { fn remove_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
unsafe { unsafe {
let ptr = ((ptr.as_ptr() as usize) & !1) as *mut GreenTokenData; let ptr = ptr.as_ptr().map_addr(|addr| addr & !IS_TOKEN_TAG);
ptr::NonNull::new_unchecked(ptr) ptr::NonNull::new_unchecked(ptr)
} }
} }

View file

@ -45,6 +45,7 @@
#![forbid(missing_debug_implementations, unconditional_recursion)] #![forbid(missing_debug_implementations, unconditional_recursion)]
#![deny(unsafe_code, missing_docs, future_incompatible)] #![deny(unsafe_code, missing_docs, future_incompatible)]
#![allow(unstable_name_collisions)] // strict provenance - must come after `future_incompatible` to take precedence
#[allow(unsafe_code)] #[allow(unsafe_code)]
mod green; mod green;

View file

@ -387,7 +387,8 @@ impl<L: Language, D> SyntaxNode<L, D> {
/// builder.token(TOKEN, "content"); /// builder.token(TOKEN, "content");
/// builder.finish_node(); /// builder.finish_node();
/// let (green, cache) = builder.finish(); /// let (green, cache) = builder.finish();
/// let root: ResolvedNode<Lang> = SyntaxNode::new_root_with_resolver(green, cache.unwrap().into_interner().unwrap()); /// let root: ResolvedNode<Lang> =
/// SyntaxNode::new_root_with_resolver(green, cache.unwrap().into_interner().unwrap());
/// assert_eq!(root.text(), "content"); /// assert_eq!(root.text(), "content");
/// ``` /// ```
#[inline] #[inline]

View file

@ -253,7 +253,12 @@ impl<L: Language, D> SyntaxToken<L, D> {
/// let tree = parse(&mut builder, "x"); /// let tree = parse(&mut builder, "x");
/// # let tree = SyntaxNode::<Lang>::new_root(builder.finish().0); /// # let tree = SyntaxNode::<Lang>::new_root(builder.finish().0);
/// let type_table = &state.type_table; /// let type_table = &state.type_table;
/// let ident = tree.children_with_tokens().next().unwrap().into_token().unwrap(); /// let ident = tree
/// .children_with_tokens()
/// .next()
/// .unwrap()
/// .into_token()
/// .unwrap();
/// let typ = type_table.type_of(ident.text_key()); /// let typ = type_table.type_of(ident.text_key());
/// ``` /// ```
#[inline] #[inline]