<commit_before>//! Replacement of service's DNS resolver

use std::{
    io::{self, ErrorKind},
    net::SocketAddr,
};

use async_trait::async_trait;
use futures::future;
use log::debug;
use shadowsocks::{dns_resolver::DnsResolve, net::ConnectOpts};
use trust_dns_proto::{
    op::{Message, Query},
    rr::{DNSClass, Name, RData, RecordType},
};

use crate::config::Mode;

use super::{client_cache::DnsClientCache, config::NameServerAddr};

pub struct DnsResolver {
    ns: NameServerAddr,
    client_cache: DnsClientCache,
    mode: Mode,
    ipv6_first: bool,
    connect_opts: ConnectOpts,
    attempts: usize,
}

impl DnsResolver {
    pub fn new(ns: NameServerAddr) -> DnsResolver {
        DnsResolver {
            ns,
            client_cache: DnsClientCache::new(5),
            mode: Mode::UdpOnly,
            ipv6_first: false,
            connect_opts: ConnectOpts::default(),
            attempts: 2,
        }
    }

    pub fn set_mode(&mut self, mode: Mode) {
        self.mode = mode;
    }

    pub fn set_ipv6_first(&mut self, ipv6_first: bool) {
        self.ipv6_first = ipv6_first;
    }

    pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) {
        self.connect_opts = connect_opts;
    }

    pub async fn lookup(&self, msg: Message) -> io::Result<Message> {
        let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty");

        for _ in 0..self.attempts {
            match self.lookup_inner(msg.clone()).await {
                Ok(m) => return Ok(m),
                Err(err) => last_err = err,
            }
        }

        Err(last_err)
    }

    async fn lookup_inner(&self, msg: Message) -> io::Result<Message> {
        match self.ns {
            NameServerAddr::SocketAddr(ns) => {
                let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty");

                // Query UDP then TCP

                if self.mode.enable_udp() {
                    match self
                        .client_cache
                        .lookup_udp_local(ns, msg.clone(), &self.connect_opts)
                        .await
                    {
                        Ok(msg) => return Ok(msg),
                        Err(err) => {
                            last_err = err.into();
                        }
                    }
                }

                if self.mode.enable_tcp() {
                    match self.client_cache.lookup_tcp_local(ns, msg, &self.connect_opts).await {
                        Ok(msg) => return Ok(msg),
                        Err(err) => {
                            last_err = err.into();
                        }
                    }
                }

                Err(last_err)
            }

            #[cfg(unix)]
            NameServerAddr::UnixSocketAddr(ref path) => self
                .client_cache
                .lookup_unix_stream(path, msg)
                .await
                .map_err(From::from),
        }
    }
}

#[async_trait]
impl DnsResolve for DnsResolver {
    async fn resolve(&self, host: &str, port: u16) -> io::Result<Vec<SocketAddr>> {
        let mut name = Name::from_utf8(host)?;
        name.set_fqdn(true);

        let mut queryv4 = Query::new();
        queryv4.set_query_class(DNSClass::IN);
        queryv4.set_name(name);

        let mut queryv6 = queryv4.clone();
        queryv4.set_query_type(RecordType::A);
        queryv6.set_query_type(RecordType::AAAA);

        let mut msgv4 = Message::new();
        msgv4.set_recursion_desired(true);
        msgv4.add_query(queryv4);

        let mut msgv6 = Message::new();
        msgv6.set_recursion_desired(true);
        msgv6.add_query(queryv6);

        let (res_v4, res_v6) = future::join(self.lookup(msgv4), self.lookup(msgv6)).await;

        if res_v4.is_err() && res_v6.is_err() {
            return if self.ipv6_first {
                Err(res_v6.unwrap_err())
            } else {
                Err(res_v4.unwrap_err())
            };
        }

        let mut vaddr = Vec::new();

        if self.ipv6_first {
            match res_v6 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            _ => {
                                return Err(io::Error::new(ErrorKind::InvalidData, "unexpected rdata section"));
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve AAAA records, error: {}", err);
                }
            }

            match res_v4 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            _ => {
                                return Err(io::Error::new(ErrorKind::InvalidData, "unexpected rdata section"));
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve A records, error: {}", err);
                }
            }
        } else {
            match res_v4 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            _ => {
                                return Err(io::Error::new(ErrorKind::InvalidData, "unexpected rdata section"));
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve A records, error: {}", err);
                }
            }

            match res_v6 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            _ => {
                                return Err(io::Error::new(ErrorKind::InvalidData, "unexpected rdata section"));
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve AAAA records, error: {}", err);
                }
            }
        }

        Ok(vaddr)
    }
}
<commit_msg>skip unused rdata section<commit_after>//! Replacement of service's DNS resolver

use std::{
    io::{self, ErrorKind},
    net::SocketAddr,
};

use async_trait::async_trait;
use futures::future;
use log::{debug, trace};
use shadowsocks::{dns_resolver::DnsResolve, net::ConnectOpts};
use trust_dns_proto::{
    op::{Message, Query},
    rr::{DNSClass, Name, RData, RecordType},
};

use crate::config::Mode;

use super::{client_cache::DnsClientCache, config::NameServerAddr};

pub struct DnsResolver {
    ns: NameServerAddr,
    client_cache: DnsClientCache,
    mode: Mode,
    ipv6_first: bool,
    connect_opts: ConnectOpts,
    attempts: usize,
}

impl DnsResolver {
    pub fn new(ns: NameServerAddr) -> DnsResolver {
        DnsResolver {
            ns,
            client_cache: DnsClientCache::new(5),
            mode: Mode::UdpOnly,
            ipv6_first: false,
            connect_opts: ConnectOpts::default(),
            attempts: 2,
        }
    }

    pub fn set_mode(&mut self, mode: Mode) {
        self.mode = mode;
    }

    pub fn set_ipv6_first(&mut self, ipv6_first: bool) {
        self.ipv6_first = ipv6_first;
    }

    pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) {
        self.connect_opts = connect_opts;
    }

    pub async fn lookup(&self, msg: Message) -> io::Result<Message> {
        let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty");

        for _ in 0..self.attempts {
            match self.lookup_inner(msg.clone()).await {
                Ok(m) => return Ok(m),
                Err(err) => last_err = err,
            }
        }

        Err(last_err)
    }

    async fn lookup_inner(&self, msg: Message) -> io::Result<Message> {
        match self.ns {
            NameServerAddr::SocketAddr(ns) => {
                let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty");

                // Query UDP then TCP

                if self.mode.enable_udp() {
                    match self
                        .client_cache
                        .lookup_udp_local(ns, msg.clone(), &self.connect_opts)
                        .await
                    {
                        Ok(msg) => return Ok(msg),
                        Err(err) => {
                            last_err = err.into();
                        }
                    }
                }

                if self.mode.enable_tcp() {
                    match self.client_cache.lookup_tcp_local(ns, msg, &self.connect_opts).await {
                        Ok(msg) => return Ok(msg),
                        Err(err) => {
                            last_err = err.into();
                        }
                    }
                }

                Err(last_err)
            }

            #[cfg(unix)]
            NameServerAddr::UnixSocketAddr(ref path) => self
                .client_cache
                .lookup_unix_stream(path, msg)
                .await
                .map_err(From::from),
        }
    }
}

#[async_trait]
impl DnsResolve for DnsResolver {
    async fn resolve(&self, host: &str, port: u16) -> io::Result<Vec<SocketAddr>> {
        let mut name = Name::from_utf8(host)?;
        name.set_fqdn(true);

        let mut queryv4 = Query::new();
        queryv4.set_query_class(DNSClass::IN);
        queryv4.set_name(name);

        let mut queryv6 = queryv4.clone();
        queryv4.set_query_type(RecordType::A);
        queryv6.set_query_type(RecordType::AAAA);

        let mut msgv4 = Message::new();
        msgv4.set_recursion_desired(true);
        msgv4.add_query(queryv4);

        let mut msgv6 = Message::new();
        msgv6.set_recursion_desired(true);
        msgv6.add_query(queryv6);

        let (res_v4, res_v6) = future::join(self.lookup(msgv4), self.lookup(msgv6)).await;

        if res_v4.is_err() && res_v6.is_err() {
            return if self.ipv6_first {
                Err(res_v6.unwrap_err())
            } else {
                Err(res_v4.unwrap_err())
            };
        }

        let mut vaddr = Vec::new();

        if self.ipv6_first {
            match res_v6 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            ref rdata => {
                                trace!("skipped rdata {:?}", rdata);
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve AAAA records, error: {}", err);
                }
            }

            match res_v4 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            ref rdata => {
                                trace!("skipped rdata {:?}", rdata);
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve A records, error: {}", err);
                }
            }
        } else {
            match res_v4 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            ref rdata => {
                                trace!("skipped rdata {:?}", rdata);
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve A records, error: {}", err);
                }
            }

            match res_v6 {
                Ok(res) => {
                    for record in res.answers() {
                        match *record.rdata() {
                            RData::A(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            RData::AAAA(addr) => vaddr.push(SocketAddr::new(addr.into(), port)),
                            ref rdata => {
                                trace!("skipped rdata {:?}", rdata);
                            }
                        }
                    }
                }
                Err(err) => {
                    debug!("failed to resolve AAAA records, error: {}", err);
                }
            }
        }

        Ok(vaddr)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::env;
use std::fs;
use std::os::unix::io::RawFd;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;

use sys_util::{EventFd, GuestMemory, PollContext, PollToken};
use tpm2;

use super::{DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_TPM};

const QUEUE_SIZE: u16 = 1;
const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE];

// Simply store TPM state in /tmp/tpm-simulator. Before shipping this feature,
// will need to move state under /run/vm instead. https://crbug.com/921841
const SIMULATOR_DIR: &str = "/tmp/tpm-simulator";

struct Worker {
    queue: Queue,
    mem: GuestMemory,
    interrupt_status: Arc<AtomicUsize>,
    interrupt_evt: EventFd,
    interrupt_resample_evt: EventFd,
    device: Device,
}

struct Device {
    simulator: tpm2::Simulator,
    response: Option<Vec<u8>>,
}

impl Device {
    fn perform_send(&mut self, mem: &GuestMemory, avail_desc: DescriptorChain) -> u32 {
        if self.response.is_some() {
            error!("vtpm encountered unexpected send");
            return 0;
        }

        let mut len = 0;
        let mut buf = vec![0u8; avail_desc.len as usize];
        match mem.read_exact_at_addr(&mut buf, avail_desc.addr) {
            Ok(()) => {
                let response = self.simulator.execute_command(&buf);
                self.response = Some(response.to_owned());
                len = avail_desc.len;
            }
            Err(err) => {
                error!("vtpm failed read from guest memory: {}", err);
            }
        }
        len
    }

    fn perform_recv(&mut self, mem: &GuestMemory, avail_desc: DescriptorChain) -> u32 {
        let buf = match self.response.take() {
            Some(buf) => buf,
            None => {
                error!("vtpm encountered unexpected recv");
                return 0;
            }
        };

        assert!(buf.len() <= avail_desc.len as usize);

        let mut len = 0;
        match mem.write_all_at_addr(&buf, avail_desc.addr) {
            Ok(()) => len = buf.len() as u32,
            Err(err) => {
                error!("vtpm failed write to guest memory: {}", err);
            }
        }
        len
    }
}

impl Worker {
    fn process_queue(&mut self) -> bool {
        let queue = &mut self.queue;

        let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
        let mut used_count = 0;
        for avail_desc in queue.iter(&self.mem) {
            let index = avail_desc.index;
            let len = if avail_desc.is_read_only() {
                self.device.perform_send(&self.mem, avail_desc)
            } else if avail_desc.is_write_only() {
                self.device.perform_recv(&self.mem, avail_desc)
            } else {
                error!("vtpm expected either read or write descriptor");
                0
            };

            used_desc_heads[used_count] = (index, len);
            used_count += 1;
        }

        for &(desc_index, len) in &used_desc_heads[..used_count] {
            queue.add_used(&self.mem, desc_index, len);
        }
        used_count > 0
    }

    fn signal_used_queue(&self) {
        self.interrupt_status
            .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst);
        let _ = self.interrupt_evt.write(1);
    }

    fn run(&mut self, queue_evt: EventFd, kill_evt: EventFd) {
        #[derive(PollToken, Debug)]
        enum Token {
            // A request is ready on the queue.
            QueueAvailable,
            // Check if any interrupts need to be re-asserted.
            InterruptResample,
            // The parent thread requested an exit.
            Kill,
        }

        let poll_ctx = match PollContext::new()
            .and_then(|pc| pc.add(&queue_evt, Token::QueueAvailable).and(Ok(pc)))
            .and_then(|pc| {
                pc.add(&self.interrupt_resample_evt, Token::InterruptResample)
                    .and(Ok(pc))
            })
            .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc)))
        {
            Ok(pc) => pc,
            Err(e) => {
                error!("vtpm failed creating PollContext: {}", e);
                return;
            }
        };

        'poll: loop {
            let events = match poll_ctx.wait() {
                Ok(v) => v,
                Err(e) => {
                    error!("vtpm failed polling for events: {}", e);
                    break;
                }
            };

            let mut needs_interrupt = false;
            for event in events.iter_readable() {
                match event.token() {
                    Token::QueueAvailable => {
                        if let Err(e) = queue_evt.read() {
                            error!("vtpm failed reading queue EventFd: {}", e);
                            break 'poll;
                        }
                        needs_interrupt |= self.process_queue();
                    }
                    Token::InterruptResample => {
                        let _ = self.interrupt_resample_evt.read();
                        if self.interrupt_status.load(Ordering::SeqCst) != 0 {
                            let _ = self.interrupt_evt.write(1);
                        }
                    }
                    Token::Kill => break 'poll,
                }
            }
            if needs_interrupt {
                self.signal_used_queue();
            }
        }
    }
}

/// Virtio vTPM device.
pub struct Tpm {
    kill_evt: Option<EventFd>,
}

impl Tpm {
    pub fn new() -> Tpm {
        Tpm { kill_evt: None }
    }
}

impl Drop for Tpm {
    fn drop(&mut self) {
        if let Some(kill_evt) = self.kill_evt.take() {
            let _ = kill_evt.write(1);
        }
    }
}

impl VirtioDevice for Tpm {
    fn keep_fds(&self) -> Vec<RawFd> {
        Vec::new()
    }

    fn device_type(&self) -> u32 {
        TYPE_TPM
    }

    fn queue_max_sizes(&self) -> &[u16] {
        QUEUE_SIZES
    }

    fn activate(
        &mut self,
        mem: GuestMemory,
        interrupt_evt: EventFd,
        interrupt_resample_evt: EventFd,
        status: Arc<AtomicUsize>,
        mut queues: Vec<Queue>,
        mut queue_evts: Vec<EventFd>,
    ) {
        if queues.len() != 1 || queue_evts.len() != 1 {
            return;
        }

        if let Err(err) = fs::create_dir_all(SIMULATOR_DIR) {
            error!("vtpm failed to create directory for simulator: {}", err);
            return;
        }
        if let Err(err) = env::set_current_dir(SIMULATOR_DIR) {
            error!("vtpm failed to change into simulator directory: {}", err);
            return;
        }
        let simulator = tpm2::Simulator::singleton_in_current_directory();

        let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) {
            Ok(v) => v,
            Err(err) => {
                error!("vtpm failed to create kill EventFd pair: {}", err);
                return;
            }
        };
        self.kill_evt = Some(self_kill_evt);

        let queue = queues.remove(0);

        let worker_result =
            thread::Builder::new()
                .name("virtio_tpm".to_string())
                .spawn(move || {
                    let mut worker = Worker {
                        queue,
                        mem,
                        interrupt_status: status,
                        interrupt_evt,
                        interrupt_resample_evt,
                        device: Device {
                            simulator,
                            response: None,
                        },
                    };
                    worker.run(queue_evts.remove(0), kill_evt);
                });

        if let Err(e) = worker_result {
            error!("vtpm failed to spawn virtio_tpm worker: {}", e);
            return;
        }
    }
}
<commit_msg>tpm: Prepare device implementation for handling send+recv together<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::env;
use std::fmt::{self, Display};
use std::fs;
use std::ops::BitOrAssign;
use std::os::unix::io::RawFd;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;

use sys_util::{EventFd, GuestMemory, GuestMemoryError, PollContext, PollToken};
use tpm2;

use super::{DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_TPM};

const QUEUE_SIZE: u16 = 1;
const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE];

// Simply store TPM state in /tmp/tpm-simulator. Before shipping this feature,
// will need to move state under /run/vm instead. https://crbug.com/921841
const SIMULATOR_DIR: &str = "/tmp/tpm-simulator";

struct Worker {
    queue: Queue,
    mem: GuestMemory,
    interrupt_status: Arc<AtomicUsize>,
    queue_evt: EventFd,
    kill_evt: EventFd,
    interrupt_evt: EventFd,
    interrupt_resample_evt: EventFd,
    device: Device,
}

struct Device {
    simulator: tpm2::Simulator,
    response: Option<Vec<u8>>,
}

impl Device {
    fn perform_work(&mut self, mem: &GuestMemory, desc: DescriptorChain) -> Result<u32> {
        if desc.is_read_only() {
            self.perform_send(&mem, desc)
        } else if desc.is_write_only() {
            self.perform_recv(&mem, desc)
        } else {
            Err(Error::ExpectedReadOrWrite)
        }
    }

    fn perform_send(&mut self, mem: &GuestMemory, desc: DescriptorChain) -> Result<u32> {
        if self.response.is_some() {
            return Err(Error::UnexpectedSend);
        }

        let mut buf = vec![0u8; desc.len as usize];
        mem.read_exact_at_addr(&mut buf, desc.addr)
            .map_err(Error::Read)?;

        let response = self.simulator.execute_command(&buf);
        self.response = Some(response.to_owned());
        Ok(desc.len)
    }

    fn perform_recv(&mut self, mem: &GuestMemory, desc: DescriptorChain) -> Result<u32> {
        let response = self.response.take().ok_or(Error::UnexpectedRecv)?;

        if response.len() > desc.len as usize {
            return Err(Error::SmallBuffer {
                size: desc.len as usize,
                required: response.len(),
            });
        }

        mem.write_all_at_addr(&response, desc.addr)
            .map_err(Error::Write)?;

        Ok(response.len() as u32)
    }
}

impl Worker {
    fn process_queue(&mut self) -> NeedsInterrupt {
        let avail_desc = match self.queue.iter(&self.mem).next() {
            Some(avail_desc) => avail_desc,
            None => return NeedsInterrupt::No,
        };

        let index = avail_desc.index;

        let len = match self.device.perform_work(&self.mem, avail_desc) {
            Ok(len) => len,
            Err(err) => {
                error!("{}", err);
                0
            }
        };

        self.queue.add_used(&self.mem, index, len);
        NeedsInterrupt::Yes
    }

    fn signal_used_queue(&self) {
        self.interrupt_status
            .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst);
        let _ = self.interrupt_evt.write(1);
    }

    fn run(mut self) {
        #[derive(PollToken, Debug)]
        enum Token {
            // A request is ready on the queue.
            QueueAvailable,
            // Check if any interrupts need to be re-asserted.
            InterruptResample,
            // The parent thread requested an exit.
            Kill,
        }

        let poll_ctx = match PollContext::new()
            .and_then(|pc| pc.add(&self.queue_evt, Token::QueueAvailable).and(Ok(pc)))
            .and_then(|pc| {
                pc.add(&self.interrupt_resample_evt, Token::InterruptResample)
                    .and(Ok(pc))
            })
            .and_then(|pc| pc.add(&self.kill_evt, Token::Kill).and(Ok(pc)))
        {
            Ok(pc) => pc,
            Err(e) => {
                error!("vtpm failed creating PollContext: {}", e);
                return;
            }
        };

        'poll: loop {
            let events = match poll_ctx.wait() {
                Ok(v) => v,
                Err(e) => {
                    error!("vtpm failed polling for events: {}", e);
                    break;
                }
            };

            let mut needs_interrupt = NeedsInterrupt::No;
            for event in events.iter_readable() {
                match event.token() {
                    Token::QueueAvailable => {
                        if let Err(e) = self.queue_evt.read() {
                            error!("vtpm failed reading queue EventFd: {}", e);
                            break 'poll;
                        }
                        needs_interrupt |= self.process_queue();
                    }
                    Token::InterruptResample => {
                        let _ = self.interrupt_resample_evt.read();
                        if self.interrupt_status.load(Ordering::SeqCst) != 0 {
                            let _ = self.interrupt_evt.write(1);
                        }
                    }
                    Token::Kill => break 'poll,
                }
            }
            if needs_interrupt == NeedsInterrupt::Yes {
                self.signal_used_queue();
            }
        }
    }
}

/// Virtio vTPM device.
pub struct Tpm {
    kill_evt: Option<EventFd>,
}

impl Tpm {
    pub fn new() -> Tpm {
        Tpm { kill_evt: None }
    }
}

impl Drop for Tpm {
    fn drop(&mut self) {
        if let Some(kill_evt) = self.kill_evt.take() {
            let _ = kill_evt.write(1);
        }
    }
}

impl VirtioDevice for Tpm {
    fn keep_fds(&self) -> Vec<RawFd> {
        Vec::new()
    }

    fn device_type(&self) -> u32 {
        TYPE_TPM
    }

    fn queue_max_sizes(&self) -> &[u16] {
        QUEUE_SIZES
    }

    fn activate(
        &mut self,
        mem: GuestMemory,
        interrupt_evt: EventFd,
        interrupt_resample_evt: EventFd,
        interrupt_status: Arc<AtomicUsize>,
        mut queues: Vec<Queue>,
        mut queue_evts: Vec<EventFd>,
    ) {
        if queues.len() != 1 || queue_evts.len() != 1 {
            return;
        }
        let queue = queues.remove(0);
        let queue_evt = queue_evts.remove(0);

        if let Err(err) = fs::create_dir_all(SIMULATOR_DIR) {
            error!("vtpm failed to create directory for simulator: {}", err);
            return;
        }
        if let Err(err) = env::set_current_dir(SIMULATOR_DIR) {
            error!("vtpm failed to change into simulator directory: {}", err);
            return;
        }
        let simulator = tpm2::Simulator::singleton_in_current_directory();

        let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) {
            Ok(v) => v,
            Err(err) => {
                error!("vtpm failed to create kill EventFd pair: {}", err);
                return;
            }
        };
        self.kill_evt = Some(self_kill_evt);

        let worker = Worker {
            queue,
            mem,
            interrupt_status,
            queue_evt,
            interrupt_evt,
            interrupt_resample_evt,
            kill_evt,
            device: Device {
                simulator,
                response: None,
            },
        };

        let worker_result = thread::Builder::new()
            .name("virtio_tpm".to_string())
            .spawn(|| worker.run());

        if let Err(e) = worker_result {
            error!("vtpm failed to spawn virtio_tpm worker: {}", e);
            return;
        }
    }
}

#[derive(PartialEq)]
enum NeedsInterrupt {
    Yes,
    No,
}

impl BitOrAssign for NeedsInterrupt {
    fn bitor_assign(&mut self, rhs: NeedsInterrupt) {
        if rhs == NeedsInterrupt::Yes {
            *self = NeedsInterrupt::Yes;
        }
    }
}

type Result<T> = std::result::Result<T, Error>;

enum Error {
    ExpectedReadOrWrite,
    UnexpectedSend,
    Read(GuestMemoryError),
    UnexpectedRecv,
    SmallBuffer { size: usize, required: usize },
    Write(GuestMemoryError),
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            ExpectedReadOrWrite => write!(f, "vtpm expected either read or write descriptor"),
            UnexpectedSend => write!(f, "vtpm encountered unexpected send"),
            Read(e) => write!(f, "vtpm failed to read from guest memory: {}", e),
            UnexpectedRecv => write!(f, "vtpm encountered unexpected recv"),
            SmallBuffer { size, required } => write!(
                f,
                "vtpm response buffer is too small: {} < {}",
                size, required
            ),
            Write(e) => write!(f, "vtpm failed to write to guest memory: {}", e),
        }
    }
}
<|endoftext|>


<commit_before>//! Types and functions related to PG's and Sqlite's `ON CONFLICT` clause
//!
//! Upsert is currently supported by diesel for the following database systems:
//!
//! * PostgreSQL version 9.5 or newer
//! * Sqlite3 version 3.24.0 or newer
//!
//! See [the methods on `InsertStatement`](../query_builder/struct.InsertStatement.html#impl-2)
//! for usage examples.
//!
//! Constructing an upsert statement from an existing select statement
//! requires a where clause on sqlite due to a ambiguity in their
//! parser.
use crate::query_builder::upsert::on_conflict_actions::Excluded;

mod on_conflict_extension;

pub use self::on_conflict_extension::*;
#[cfg(feature = "postgres")]
pub use crate::pg::query_builder::on_constraint::*;

/// Represents `excluded.column` in an `ON CONFLICT DO UPDATE` clause.
pub fn excluded<T>(excluded: T) -> Excluded<T> {
    Excluded::new(excluded)
}
<commit_msg>Minor documentation improvement<commit_after>//! Types and functions related to PG's and Sqlite's `ON CONFLICT` clause
//!
//! Upsert is currently supported by diesel for the following database systems:
//!
//! * PostgreSQL version 9.5 or newer
//! * Sqlite3 version 3.24.0 or newer
//!
//! See [the methods on `InsertStatement`](../query_builder/struct.InsertStatement.html#impl-2)
//! for usage examples.
//!
//! Constructing an upsert statement from an existing select statement
//! requires a where clause on sqlite due to a ambiguity in their
//! parser. See [the corresponding documentation](https://www.sqlite.org/lang_UPSERT.html)
//! for details.
use crate::query_builder::upsert::on_conflict_actions::Excluded;

mod on_conflict_extension;

pub use self::on_conflict_extension::*;
#[cfg(feature = "postgres")]
pub use crate::pg::query_builder::on_constraint::*;

/// Represents `excluded.column` in an `ON CONFLICT DO UPDATE` clause.
pub fn excluded<T>(excluded: T) -> Excluded<T> {
    Excluded::new(excluded)
}
<|endoftext|>


<commit_before>use core::{
    mem,
    fmt,
    future::Future,
    marker::PhantomData,
    pin::Pin,
    task::{Context, Poll},
};

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + 'a>`.
///
/// This custom trait object was introduced as currently it is not possible to
/// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
/// contexts.
pub struct LocalFutureObj<'a, T> {
    future: *mut (dyn Future<Output = T> + 'static),
    drop_fn: unsafe fn(*mut (dyn Future<Output = T> + 'static)),
    _marker: PhantomData<&'a ()>,
}

impl<T> Unpin for LocalFutureObj<'_, T> {}

#[allow(single_use_lifetimes)]
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe fn remove_future_lifetime<'a, T>(ptr: *mut (dyn Future<Output = T> + 'a))
    -> *mut (dyn Future<Output = T> + 'static)
{
    mem::transmute(ptr)
}

#[allow(single_use_lifetimes)]
unsafe fn remove_drop_lifetime<'a, T>(ptr: unsafe fn (*mut (dyn Future<Output = T> + 'a)))
    -> unsafe fn(*mut (dyn Future<Output = T> + 'static))
{
    mem::transmute(ptr)
}

impl<'a, T> LocalFutureObj<'a, T> {
    /// Create a `LocalFutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + 'a>(f: F) -> LocalFutureObj<'a, T> {
        LocalFutureObj {
            future: unsafe { remove_future_lifetime(f.into_raw()) },
            drop_fn: unsafe { remove_drop_lifetime(F::drop) },
            _marker: PhantomData,
        }
    }

    /// Converts the `LocalFutureObj` into a `FutureObj`.
    ///
    /// # Safety
    ///
    /// To make this operation safe one has to ensure that the `UnsafeFutureObj`
    /// instance from which this `LocalFutureObj` was created actually
    /// implements `Send`.
    #[inline]
    pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> {
        FutureObj(self)
    }
}

impl<T> fmt::Debug for LocalFutureObj<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("LocalFutureObj")
            .finish()
    }
}

impl<'a, T> From<FutureObj<'a, T>> for LocalFutureObj<'a, T> {
    #[inline]
    fn from(f: FutureObj<'a, T>) -> LocalFutureObj<'a, T> {
        f.0
    }
}

impl<T> Future for LocalFutureObj<'_, T> {
    type Output = T;

    #[inline]
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
        unsafe {
            Pin::new_unchecked(&mut *self.future).poll(cx)
        }
    }
}

impl<T> Drop for LocalFutureObj<'_, T> {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.future)
        }
    }
}

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + Send + 'a>`.
///
/// This custom trait object was introduced as currently it is not possible to
/// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
/// contexts.
///
/// You should generally not need to use this type outside of `no_std` or when
/// implementing `Spawn`, consider using [`BoxFuture`](crate::future::BoxFuture)
/// instead.
pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);

impl<T> Unpin for FutureObj<'_, T> {}
unsafe impl<T> Send for FutureObj<'_, T> {}

impl<'a, T> FutureObj<'a, T> {
    /// Create a `FutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> FutureObj<'a, T> {
        FutureObj(LocalFutureObj::new(f))
    }
}

impl<T> fmt::Debug for FutureObj<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FutureObj")
            .finish()
    }
}

impl<T> Future for FutureObj<'_, T> {
    type Output = T;

    #[inline]
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
        Pin::new( &mut self.0 ).poll(cx)
    }
}

/// A custom implementation of a future trait object for `FutureObj`, providing
/// a vtable with drop support.
///
/// This custom representation is typically used only in `no_std` contexts,
/// where the default `Box`-based implementation is not available.
///
/// # Safety
///
/// See the safety notes on individual methods for what guarantees an
/// implementor must provide.
pub unsafe trait UnsafeFutureObj<'a, T>: 'a {
    /// Convert an owned instance into a (conceptually owned) fat pointer.
    ///
    /// # Safety
    ///
    /// ## Implementor
    ///
    /// The trait implementor must guarantee that it is safe to convert the
    /// provided `*mut (dyn Future<Output = T> + 'a)` into a `Pin<&mut (dyn
    /// Future<Output = T> + 'a)>` and call methods on it, non-reentrantly,
    /// until `UnsafeFutureObj::drop` is called with it.
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a);

    /// Drops the future represented by the given fat pointer.
    ///
    /// # Safety
    ///
    /// ## Implementor
    ///
    /// The trait implementor must guarantee that it is safe to call this
    /// function once per `into_raw` invocation.
    ///
    /// ## Caller
    ///
    /// The caller must ensure:
    ///
    ///  * the pointer passed was obtained from an `into_raw` invocation from
    ///    this same trait object
    ///  * the pointer is not currently in use as a `Pin<&mut (dyn Future<Output
    ///    = T> + 'a)>`
    ///  * the pointer must not be used again after this function is called
    unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a));
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F
where
    F: Future<Output = T> + Unpin + 'a
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        self as *mut dyn Future<Output = T>
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

unsafe impl<'a, T> UnsafeFutureObj<'a, T> for &'a mut (dyn Future<Output = T> + Unpin + 'a)
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        self as *mut dyn Future<Output = T>
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F>
where
    F: Future<Output = T> + 'a
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

unsafe impl<'a, T> UnsafeFutureObj<'a, T> for Pin<&'a mut (dyn Future<Output = T> + 'a)>
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

#[cfg(feature = "alloc")]
mod if_alloc {
    use super::*;
    use alloc::boxed::Box;

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
        where F: Future<Output = T> + 'a
    {
        fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
            Box::into_raw(self)
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Box::from_raw(ptr as *mut F))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + 'a> {
        fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
            Box::into_raw(self)
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Box::from_raw(ptr))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + Send + 'a> {
        fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
            Box::into_raw(self)
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Box::from_raw(ptr))
        }
    }

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<Box<F>>
    where
        F: Future<Output = T> + 'a
    {
        fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
            let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
            mem::forget(self);
            ptr
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Pin::from(Box::from_raw(ptr)))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + 'a>> {
        fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
            let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
            mem::forget(self);
            ptr
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Pin::from(Box::from_raw(ptr)))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + Send + 'a>> {
        fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
            let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
            mem::forget(self);
            ptr
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Pin::from(Box::from_raw(ptr)))
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a> From<Box<dyn Future<Output = ()> + Send + 'a>> for FutureObj<'a, ()> {
        fn from(boxed: Box<dyn Future<Output = ()> + Send + 'a>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a> From<Pin<Box<dyn Future<Output = ()> + Send + 'a>>> for FutureObj<'a, ()> {
        fn from(boxed: Pin<Box<dyn Future<Output = ()> + Send + 'a>>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a> From<Box<dyn Future<Output = ()> + 'a>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Box<dyn Future<Output = ()> + 'a>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a> From<Pin<Box<dyn Future<Output = ()> + 'a>>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Pin<Box<dyn Future<Output = ()> + 'a>>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }
}
<commit_msg>Add explanation why the Unpin impl is safe.<commit_after>use core::{
    mem,
    fmt,
    future::Future,
    marker::PhantomData,
    pin::Pin,
    task::{Context, Poll},
};

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + 'a>`.
///
/// This custom trait object was introduced as currently it is not possible to
/// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
/// contexts.
pub struct LocalFutureObj<'a, T> {
    future: *mut (dyn Future<Output = T> + 'static),
    drop_fn: unsafe fn(*mut (dyn Future<Output = T> + 'static)),
    _marker: PhantomData<&'a ()>,
}

// As LocalFutureObj only holds pointers, even if we move it, the pointed to values won't move,
// so this is safe as long as we don't provide any way for a user to directly access the pointers
// and move their values.
impl<T> Unpin for LocalFutureObj<'_, T> {}

#[allow(single_use_lifetimes)]
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe fn remove_future_lifetime<'a, T>(ptr: *mut (dyn Future<Output = T> + 'a))
    -> *mut (dyn Future<Output = T> + 'static)
{
    mem::transmute(ptr)
}

#[allow(single_use_lifetimes)]
unsafe fn remove_drop_lifetime<'a, T>(ptr: unsafe fn (*mut (dyn Future<Output = T> + 'a)))
    -> unsafe fn(*mut (dyn Future<Output = T> + 'static))
{
    mem::transmute(ptr)
}

impl<'a, T> LocalFutureObj<'a, T> {
    /// Create a `LocalFutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + 'a>(f: F) -> LocalFutureObj<'a, T> {
        LocalFutureObj {
            future: unsafe { remove_future_lifetime(f.into_raw()) },
            drop_fn: unsafe { remove_drop_lifetime(F::drop) },
            _marker: PhantomData,
        }
    }

    /// Converts the `LocalFutureObj` into a `FutureObj`.
    ///
    /// # Safety
    ///
    /// To make this operation safe one has to ensure that the `UnsafeFutureObj`
    /// instance from which this `LocalFutureObj` was created actually
    /// implements `Send`.
    #[inline]
    pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> {
        FutureObj(self)
    }
}

impl<T> fmt::Debug for LocalFutureObj<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("LocalFutureObj")
            .finish()
    }
}

impl<'a, T> From<FutureObj<'a, T>> for LocalFutureObj<'a, T> {
    #[inline]
    fn from(f: FutureObj<'a, T>) -> LocalFutureObj<'a, T> {
        f.0
    }
}

impl<T> Future for LocalFutureObj<'_, T> {
    type Output = T;

    #[inline]
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
        unsafe {
            Pin::new_unchecked(&mut *self.future).poll(cx)
        }
    }
}

impl<T> Drop for LocalFutureObj<'_, T> {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.future)
        }
    }
}

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + Send + 'a>`.
///
/// This custom trait object was introduced as currently it is not possible to
/// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
/// contexts.
///
/// You should generally not need to use this type outside of `no_std` or when
/// implementing `Spawn`, consider using [`BoxFuture`](crate::future::BoxFuture)
/// instead.
pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);

impl<T> Unpin for FutureObj<'_, T> {}
unsafe impl<T> Send for FutureObj<'_, T> {}

impl<'a, T> FutureObj<'a, T> {
    /// Create a `FutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> FutureObj<'a, T> {
        FutureObj(LocalFutureObj::new(f))
    }
}

impl<T> fmt::Debug for FutureObj<'_, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FutureObj")
            .finish()
    }
}

impl<T> Future for FutureObj<'_, T> {
    type Output = T;

    #[inline]
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
        Pin::new( &mut self.0 ).poll(cx)
    }
}

/// A custom implementation of a future trait object for `FutureObj`, providing
/// a vtable with drop support.
///
/// This custom representation is typically used only in `no_std` contexts,
/// where the default `Box`-based implementation is not available.
///
/// # Safety
///
/// See the safety notes on individual methods for what guarantees an
/// implementor must provide.
pub unsafe trait UnsafeFutureObj<'a, T>: 'a {
    /// Convert an owned instance into a (conceptually owned) fat pointer.
    ///
    /// # Safety
    ///
    /// ## Implementor
    ///
    /// The trait implementor must guarantee that it is safe to convert the
    /// provided `*mut (dyn Future<Output = T> + 'a)` into a `Pin<&mut (dyn
    /// Future<Output = T> + 'a)>` and call methods on it, non-reentrantly,
    /// until `UnsafeFutureObj::drop` is called with it.
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a);

    /// Drops the future represented by the given fat pointer.
    ///
    /// # Safety
    ///
    /// ## Implementor
    ///
    /// The trait implementor must guarantee that it is safe to call this
    /// function once per `into_raw` invocation.
    ///
    /// ## Caller
    ///
    /// The caller must ensure:
    ///
    ///  * the pointer passed was obtained from an `into_raw` invocation from
    ///    this same trait object
    ///  * the pointer is not currently in use as a `Pin<&mut (dyn Future<Output
    ///    = T> + 'a)>`
    ///  * the pointer must not be used again after this function is called
    unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a));
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F
where
    F: Future<Output = T> + Unpin + 'a
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        self as *mut dyn Future<Output = T>
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

unsafe impl<'a, T> UnsafeFutureObj<'a, T> for &'a mut (dyn Future<Output = T> + Unpin + 'a)
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        self as *mut dyn Future<Output = T>
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F>
where
    F: Future<Output = T> + 'a
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

unsafe impl<'a, T> UnsafeFutureObj<'a, T> for Pin<&'a mut (dyn Future<Output = T> + 'a)>
{
    fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
        unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
    }

    unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
}

#[cfg(feature = "alloc")]
mod if_alloc {
    use super::*;
    use alloc::boxed::Box;

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
        where F: Future<Output = T> + 'a
    {
        fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
            Box::into_raw(self)
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Box::from_raw(ptr as *mut F))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + 'a> {
        fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
            Box::into_raw(self)
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Box::from_raw(ptr))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + Send + 'a> {
        fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
            Box::into_raw(self)
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Box::from_raw(ptr))
        }
    }

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<Box<F>>
    where
        F: Future<Output = T> + 'a
    {
        fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
            let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
            mem::forget(self);
            ptr
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Pin::from(Box::from_raw(ptr)))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + 'a>> {
        fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
            let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
            mem::forget(self);
            ptr
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Pin::from(Box::from_raw(ptr)))
        }
    }

    unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + Send + 'a>> {
        fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
            let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
            mem::forget(self);
            ptr
        }

        unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
            drop(Pin::from(Box::from_raw(ptr)))
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a> From<Box<dyn Future<Output = ()> + Send + 'a>> for FutureObj<'a, ()> {
        fn from(boxed: Box<dyn Future<Output = ()> + Send + 'a>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a> From<Pin<Box<dyn Future<Output = ()> + Send + 'a>>> for FutureObj<'a, ()> {
        fn from(boxed: Pin<Box<dyn Future<Output = ()> + Send + 'a>>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a> From<Box<dyn Future<Output = ()> + 'a>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Box<dyn Future<Output = ()> + 'a>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a> From<Pin<Box<dyn Future<Output = ()> + 'a>>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Pin<Box<dyn Future<Output = ()> + 'a>>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }
}
<|endoftext|>


<commit_before>//! This module contains the machinery necessary to detect infinite loops
//! during const-evaluation by taking snapshots of the state of the interpreter
//! at regular intervals.

// This lives in `interpret` because it needs access to all sots of private state.  However,
// it is not used by the general miri engine, just by CTFE.

use std::hash::{Hash, Hasher};

use rustc::ich::StableHashingContextProvider;
use rustc::mir;
use rustc::mir::interpret::{
    AllocId, Pointer, Scalar,
    Relocations, Allocation, UndefMask,
    EvalResult, EvalErrorKind,
};

use rustc::ty::{self, TyCtxt};
use rustc::ty::layout::Align;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use syntax::ast::Mutability;
use syntax::source_map::Span;

use super::eval_context::{LocalState, StackPopCleanup};
use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef, LocalValue};
use const_eval::CompileTimeInterpreter;

#[derive(Default)]
pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir> {
    /// The set of all `EvalSnapshot` *hashes* observed by this detector.
    ///
    /// When a collision occurs in this table, we store the full snapshot in
    /// `snapshots`.
    hashes: FxHashSet<u64>,

    /// The set of all `EvalSnapshot`s observed by this detector.
    ///
    /// An `EvalSnapshot` will only be fully cloned once it has caused a
    /// collision in `hashes`. As a result, the detector must observe at least
    /// *two* full cycles of an infinite loop before it triggers.
    snapshots: FxHashSet<EvalSnapshot<'a, 'mir, 'tcx>>,
}

impl<'a, 'mir, 'tcx> InfiniteLoopDetector<'a, 'mir, 'tcx>
{
    pub fn observe_and_analyze<'b>(
        &mut self,
        tcx: &TyCtxt<'b, 'tcx, 'tcx>,
        span: Span,
        memory: &Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
        stack: &[Frame<'mir, 'tcx>],
    ) -> EvalResult<'tcx, ()> {
        // Compute stack's hash before copying anything
        let mut hcx = tcx.get_stable_hashing_context();
        let mut hasher = StableHasher::<u64>::new();
        stack.hash_stable(&mut hcx, &mut hasher);
        let hash = hasher.finish();

        // Check if we know that hash already
        if self.hashes.is_empty() {
            // FIXME(#49980): make this warning a lint
            tcx.sess.span_warn(span,
                "Constant evaluating a complex constant, this might take some time");
        }
        if self.hashes.insert(hash) {
            // No collision
            return Ok(())
        }

        // We need to make a full copy. NOW things that to get really expensive.
        info!("snapshotting the state of the interpreter");

        if self.snapshots.insert(EvalSnapshot::new(memory, stack)) {
            // Spurious collision or first cycle
            return Ok(())
        }

        // Second cycle
        Err(EvalErrorKind::InfiniteLoop.into())
    }
}

trait SnapshotContext<'a> {
    fn resolve(&'a self, id: &AllocId) -> Option<&'a Allocation>;
}

/// Taking a snapshot of the evaluation context produces a view of
/// the state of the interpreter that is invariant to `AllocId`s.
trait Snapshot<'a, Ctx: SnapshotContext<'a>> {
    type Item;
    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item;
}

macro_rules! __impl_snapshot_field {
    ($field:ident, $ctx:expr) => ($field.snapshot($ctx));
    ($field:ident, $ctx:expr, $delegate:expr) => ($delegate);
}

// This assumes the type has two type parameters, first for the tag (set to `()`),
// then for the id
macro_rules! impl_snapshot_for {
    // FIXME(mark-i-m): Some of these should be `?` rather than `*`.
    (enum $enum_name:ident {
        $( $variant:ident $( ( $($field:ident $(-> $delegate:expr)*),* ) )* ),* $(,)*
    }) => {

        impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name
            where Ctx: self::SnapshotContext<'a>,
        {
            type Item = $enum_name<(), AllocIdSnapshot<'a>>;

            #[inline]
            fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
                match *self {
                    $(
                        $enum_name::$variant $( ( $(ref $field),* ) )* =>
                            $enum_name::$variant $(
                                ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),* ),
                            )*
                    )*
                }
            }
        }
    };

    // FIXME(mark-i-m): same here.
    (struct $struct_name:ident { $($field:ident $(-> $delegate:expr)*),*  $(,)* }) => {
        impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name
            where Ctx: self::SnapshotContext<'a>,
        {
            type Item = $struct_name<(), AllocIdSnapshot<'a>>;

            #[inline]
            fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
                let $struct_name {
                    $(ref $field),*
                } = *self;

                $struct_name {
                    $( $field: __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),*
                }
            }
        }
    };
}

impl<'a, Ctx, T> Snapshot<'a, Ctx> for Option<T>
    where Ctx: SnapshotContext<'a>,
          T: Snapshot<'a, Ctx>
{
    type Item = Option<<T as Snapshot<'a, Ctx>>::Item>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        match self {
            Some(x) => Some(x.snapshot(ctx)),
            None => None,
        }
    }
}

#[derive(Eq, PartialEq)]
struct AllocIdSnapshot<'a>(Option<AllocationSnapshot<'a>>);

impl<'a, Ctx> Snapshot<'a, Ctx> for AllocId
    where Ctx: SnapshotContext<'a>,
{
    type Item = AllocIdSnapshot<'a>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        AllocIdSnapshot(ctx.resolve(self).map(|alloc| alloc.snapshot(ctx)))
    }
}

impl_snapshot_for!(struct Pointer {
    alloc_id,
    offset -> *offset, // just copy offset verbatim
    tag -> *tag, // just copy tag
});

impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar
    where Ctx: SnapshotContext<'a>,
{
    type Item = Scalar<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        match self {
            Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)),
            Scalar::Bits{ size, bits } => Scalar::Bits {
                size: *size,
                bits: *bits,
            },
        }
    }
}

impl_snapshot_for!(enum ScalarMaybeUndef {
    Scalar(s),
    Undef,
});

impl_stable_hash_for!(struct ::interpret::MemPlace {
    ptr,
    align,
    meta,
});
impl_snapshot_for!(struct MemPlace {
    ptr,
    meta,
    align -> *align, // just copy alignment verbatim
});

impl_stable_hash_for!(enum ::interpret::Place {
    Ptr(mem_place),
    Local { frame, local },
});
impl<'a, Ctx> Snapshot<'a, Ctx> for Place
    where Ctx: SnapshotContext<'a>,
{
    type Item = Place<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        match self {
            Place::Ptr(p) => Place::Ptr(p.snapshot(ctx)),

            Place::Local{ frame, local } => Place::Local{
                frame: *frame,
                local: *local,
            },
        }
    }
}

impl_stable_hash_for!(enum ::interpret::Immediate {
    Scalar(x),
    ScalarPair(x, y),
});
impl_snapshot_for!(enum Immediate {
    Scalar(s),
    ScalarPair(s, t),
});

impl_stable_hash_for!(enum ::interpret::Operand {
    Immediate(x),
    Indirect(x),
});
impl_snapshot_for!(enum Operand {
    Immediate(v),
    Indirect(m),
});

impl_stable_hash_for!(enum ::interpret::LocalValue {
    Dead,
    Live(x),
});
impl_snapshot_for!(enum LocalValue {
    Live(v),
    Dead,
});

impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations
    where Ctx: SnapshotContext<'a>,
{
    type Item = Relocations<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        Relocations::from_presorted(self.iter()
            .map(|(size, ((), id))| (*size, ((), id.snapshot(ctx))))
            .collect())
    }
}

#[derive(Eq, PartialEq)]
struct AllocationSnapshot<'a> {
    bytes: &'a [u8],
    relocations: Relocations<(), AllocIdSnapshot<'a>>,
    undef_mask: &'a UndefMask,
    align: &'a Align,
    mutability: &'a Mutability,
}

impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation
    where Ctx: SnapshotContext<'a>,
{
    type Item = AllocationSnapshot<'a>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        let Allocation { bytes, relocations, undef_mask, align, mutability, extra: () } = self;

        AllocationSnapshot {
            bytes,
            undef_mask,
            align,
            mutability,
            relocations: relocations.snapshot(ctx),
        }
    }
}

impl_stable_hash_for!(enum ::interpret::eval_context::StackPopCleanup {
    Goto(block),
    None { cleanup },
});

#[derive(Eq, PartialEq)]
struct FrameSnapshot<'a, 'tcx: 'a> {
    instance: &'a ty::Instance<'tcx>,
    span: &'a Span,
    return_to_block: &'a StackPopCleanup,
    return_place: Option<Place<(), AllocIdSnapshot<'a>>>,
    locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
    block: &'a mir::BasicBlock,
    stmt: usize,
}

impl_stable_hash_for!(impl<'mir, 'tcx: 'mir> for struct Frame<'mir, 'tcx> {
    mir,
    instance,
    span,
    return_to_block,
    return_place -> (return_place.as_ref().map(|r| &**r)),
    locals,
    block,
    stmt,
    extra,
});

impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
    where Ctx: SnapshotContext<'a>,
{
    type Item = FrameSnapshot<'a, 'tcx>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        let Frame {
            mir: _,
            instance,
            span,
            return_to_block,
            return_place,
            locals,
            block,
            stmt,
            extra: _,
        } = self;

        FrameSnapshot {
            instance,
            span,
            return_to_block,
            block,
            stmt: *stmt,
            return_place: return_place.map(|r| r.snapshot(ctx)),
            locals: locals.iter().map(|local| local.snapshot(ctx)).collect(),
        }
    }
}

impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx>
    where Ctx: SnapshotContext<'a>,
{
    type Item = LocalValue<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        self.state.snapshot(ctx)
    }
}

impl_stable_hash_for!(struct LocalState<'tcx> {
    state,
    layout -> _,
});

impl<'a, 'b, 'mir, 'tcx: 'a+'mir> SnapshotContext<'b>
    for Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>
{
    fn resolve(&'b self, id: &AllocId) -> Option<&'b Allocation> {
        self.get(*id).ok()
    }
}

/// The virtual machine state during const-evaluation at a given point in time.
/// We assume the `CompileTimeInterpreter` has no interesting extra state that
/// is worth considering here.
struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir> {
    memory: Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
    stack: Vec<Frame<'mir, 'tcx>>,
}

impl<'a, 'mir, 'tcx: 'a + 'mir> EvalSnapshot<'a, 'mir, 'tcx>
{
    fn new(
        memory: &Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
        stack: &[Frame<'mir, 'tcx>]
    ) -> Self {
        EvalSnapshot {
            memory: memory.clone(),
            stack: stack.into(),
        }
    }

    // Used to compare two snapshots
    fn snapshot(&'b self)
        -> Vec<FrameSnapshot<'b, 'tcx>>
    {
        // Start with the stack, iterate and recursively snapshot
        self.stack.iter().map(|frame| frame.snapshot(&self.memory)).collect()
    }

}

impl<'a, 'mir, 'tcx> Hash for EvalSnapshot<'a, 'mir, 'tcx>
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        // Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2)
        let mut hcx = self.memory.tcx.get_stable_hashing_context();
        let mut hasher = StableHasher::<u64>::new();
        self.hash_stable(&mut hcx, &mut hasher);
        hasher.finish().hash(state)
    }
}

impl_stable_hash_for!(impl<'tcx, 'b, 'mir> for struct EvalSnapshot<'b, 'mir, 'tcx> {
    // Not hashing memory: Avoid hashing memory all the time during execution
    memory -> _,
    stack,
});

impl<'a, 'mir, 'tcx> Eq for EvalSnapshot<'a, 'mir, 'tcx>
{}

impl<'a, 'mir, 'tcx> PartialEq for EvalSnapshot<'a, 'mir, 'tcx>
{
    fn eq(&self, other: &Self) -> bool {
        // FIXME: This looks to be a *ridicolously expensive* comparison operation.
        // Doesn't this make tons of copies?  Either `snapshot` is very badly named,
        // or it does!
        self.snapshot() == other.snapshot()
    }
}
<commit_msg>Failure resistent trait implementing<commit_after>//! This module contains the machinery necessary to detect infinite loops
//! during const-evaluation by taking snapshots of the state of the interpreter
//! at regular intervals.

// This lives in `interpret` because it needs access to all sots of private state.  However,
// it is not used by the general miri engine, just by CTFE.

use std::hash::{Hash, Hasher};

use rustc::ich::StableHashingContextProvider;
use rustc::mir;
use rustc::mir::interpret::{
    AllocId, Pointer, Scalar,
    Relocations, Allocation, UndefMask,
    EvalResult, EvalErrorKind,
};

use rustc::ty::{self, TyCtxt};
use rustc::ty::layout::Align;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use syntax::ast::Mutability;
use syntax::source_map::Span;

use super::eval_context::{LocalState, StackPopCleanup};
use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef, LocalValue};
use const_eval::CompileTimeInterpreter;

#[derive(Default)]
pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir> {
    /// The set of all `EvalSnapshot` *hashes* observed by this detector.
    ///
    /// When a collision occurs in this table, we store the full snapshot in
    /// `snapshots`.
    hashes: FxHashSet<u64>,

    /// The set of all `EvalSnapshot`s observed by this detector.
    ///
    /// An `EvalSnapshot` will only be fully cloned once it has caused a
    /// collision in `hashes`. As a result, the detector must observe at least
    /// *two* full cycles of an infinite loop before it triggers.
    snapshots: FxHashSet<EvalSnapshot<'a, 'mir, 'tcx>>,
}

impl<'a, 'mir, 'tcx> InfiniteLoopDetector<'a, 'mir, 'tcx>
{
    pub fn observe_and_analyze<'b>(
        &mut self,
        tcx: &TyCtxt<'b, 'tcx, 'tcx>,
        span: Span,
        memory: &Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
        stack: &[Frame<'mir, 'tcx>],
    ) -> EvalResult<'tcx, ()> {
        // Compute stack's hash before copying anything
        let mut hcx = tcx.get_stable_hashing_context();
        let mut hasher = StableHasher::<u64>::new();
        stack.hash_stable(&mut hcx, &mut hasher);
        let hash = hasher.finish();

        // Check if we know that hash already
        if self.hashes.is_empty() {
            // FIXME(#49980): make this warning a lint
            tcx.sess.span_warn(span,
                "Constant evaluating a complex constant, this might take some time");
        }
        if self.hashes.insert(hash) {
            // No collision
            return Ok(())
        }

        // We need to make a full copy. NOW things that to get really expensive.
        info!("snapshotting the state of the interpreter");

        if self.snapshots.insert(EvalSnapshot::new(memory, stack)) {
            // Spurious collision or first cycle
            return Ok(())
        }

        // Second cycle
        Err(EvalErrorKind::InfiniteLoop.into())
    }
}

trait SnapshotContext<'a> {
    fn resolve(&'a self, id: &AllocId) -> Option<&'a Allocation>;
}

/// Taking a snapshot of the evaluation context produces a view of
/// the state of the interpreter that is invariant to `AllocId`s.
trait Snapshot<'a, Ctx: SnapshotContext<'a>> {
    type Item;
    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item;
}

macro_rules! __impl_snapshot_field {
    ($field:ident, $ctx:expr) => ($field.snapshot($ctx));
    ($field:ident, $ctx:expr, $delegate:expr) => ($delegate);
}

// This assumes the type has two type parameters, first for the tag (set to `()`),
// then for the id
macro_rules! impl_snapshot_for {
    // FIXME(mark-i-m): Some of these should be `?` rather than `*`.
    (enum $enum_name:ident {
        $( $variant:ident $( ( $($field:ident $(-> $delegate:expr)*),* ) )* ),* $(,)*
    }) => {

        impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name
            where Ctx: self::SnapshotContext<'a>,
        {
            type Item = $enum_name<(), AllocIdSnapshot<'a>>;

            #[inline]
            fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
                match *self {
                    $(
                        $enum_name::$variant $( ( $(ref $field),* ) )* =>
                            $enum_name::$variant $(
                                ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),* ),
                            )*
                    )*
                }
            }
        }
    };

    // FIXME(mark-i-m): same here.
    (struct $struct_name:ident { $($field:ident $(-> $delegate:expr)*),*  $(,)* }) => {
        impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name
            where Ctx: self::SnapshotContext<'a>,
        {
            type Item = $struct_name<(), AllocIdSnapshot<'a>>;

            #[inline]
            fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
                let $struct_name {
                    $(ref $field),*
                } = *self;

                $struct_name {
                    $( $field: __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),*
                }
            }
        }
    };
}

impl<'a, Ctx, T> Snapshot<'a, Ctx> for Option<T>
    where Ctx: SnapshotContext<'a>,
          T: Snapshot<'a, Ctx>
{
    type Item = Option<<T as Snapshot<'a, Ctx>>::Item>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        match self {
            Some(x) => Some(x.snapshot(ctx)),
            None => None,
        }
    }
}

#[derive(Eq, PartialEq)]
struct AllocIdSnapshot<'a>(Option<AllocationSnapshot<'a>>);

impl<'a, Ctx> Snapshot<'a, Ctx> for AllocId
    where Ctx: SnapshotContext<'a>,
{
    type Item = AllocIdSnapshot<'a>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        AllocIdSnapshot(ctx.resolve(self).map(|alloc| alloc.snapshot(ctx)))
    }
}

impl_snapshot_for!(struct Pointer {
    alloc_id,
    offset -> *offset, // just copy offset verbatim
    tag -> *tag, // just copy tag
});

impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar
    where Ctx: SnapshotContext<'a>,
{
    type Item = Scalar<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        match self {
            Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)),
            Scalar::Bits{ size, bits } => Scalar::Bits {
                size: *size,
                bits: *bits,
            },
        }
    }
}

impl_snapshot_for!(enum ScalarMaybeUndef {
    Scalar(s),
    Undef,
});

impl_stable_hash_for!(struct ::interpret::MemPlace {
    ptr,
    align,
    meta,
});
impl_snapshot_for!(struct MemPlace {
    ptr,
    meta,
    align -> *align, // just copy alignment verbatim
});

impl_stable_hash_for!(enum ::interpret::Place {
    Ptr(mem_place),
    Local { frame, local },
});
impl<'a, Ctx> Snapshot<'a, Ctx> for Place
    where Ctx: SnapshotContext<'a>,
{
    type Item = Place<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        match self {
            Place::Ptr(p) => Place::Ptr(p.snapshot(ctx)),

            Place::Local{ frame, local } => Place::Local{
                frame: *frame,
                local: *local,
            },
        }
    }
}

impl_stable_hash_for!(enum ::interpret::Immediate {
    Scalar(x),
    ScalarPair(x, y),
});
impl_snapshot_for!(enum Immediate {
    Scalar(s),
    ScalarPair(s, t),
});

impl_stable_hash_for!(enum ::interpret::Operand {
    Immediate(x),
    Indirect(x),
});
impl_snapshot_for!(enum Operand {
    Immediate(v),
    Indirect(m),
});

impl_stable_hash_for!(enum ::interpret::LocalValue {
    Dead,
    Live(x),
});
impl_snapshot_for!(enum LocalValue {
    Live(v),
    Dead,
});

impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations
    where Ctx: SnapshotContext<'a>,
{
    type Item = Relocations<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        Relocations::from_presorted(self.iter()
            .map(|(size, ((), id))| (*size, ((), id.snapshot(ctx))))
            .collect())
    }
}

#[derive(Eq, PartialEq)]
struct AllocationSnapshot<'a> {
    bytes: &'a [u8],
    relocations: Relocations<(), AllocIdSnapshot<'a>>,
    undef_mask: &'a UndefMask,
    align: &'a Align,
    mutability: &'a Mutability,
}

impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation
    where Ctx: SnapshotContext<'a>,
{
    type Item = AllocationSnapshot<'a>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        let Allocation { bytes, relocations, undef_mask, align, mutability, extra: () } = self;

        AllocationSnapshot {
            bytes,
            undef_mask,
            align,
            mutability,
            relocations: relocations.snapshot(ctx),
        }
    }
}

impl_stable_hash_for!(enum ::interpret::eval_context::StackPopCleanup {
    Goto(block),
    None { cleanup },
});

#[derive(Eq, PartialEq)]
struct FrameSnapshot<'a, 'tcx: 'a> {
    instance: &'a ty::Instance<'tcx>,
    span: &'a Span,
    return_to_block: &'a StackPopCleanup,
    return_place: Option<Place<(), AllocIdSnapshot<'a>>>,
    locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
    block: &'a mir::BasicBlock,
    stmt: usize,
}

impl_stable_hash_for!(impl<'mir, 'tcx: 'mir> for struct Frame<'mir, 'tcx> {
    mir,
    instance,
    span,
    return_to_block,
    return_place -> (return_place.as_ref().map(|r| &**r)),
    locals,
    block,
    stmt,
    extra,
});

impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
    where Ctx: SnapshotContext<'a>,
{
    type Item = FrameSnapshot<'a, 'tcx>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        let Frame {
            mir: _,
            instance,
            span,
            return_to_block,
            return_place,
            locals,
            block,
            stmt,
            extra: _,
        } = self;

        FrameSnapshot {
            instance,
            span,
            return_to_block,
            block,
            stmt: *stmt,
            return_place: return_place.map(|r| r.snapshot(ctx)),
            locals: locals.iter().map(|local| local.snapshot(ctx)).collect(),
        }
    }
}

impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx>
    where Ctx: SnapshotContext<'a>,
{
    type Item = LocalValue<(), AllocIdSnapshot<'a>>;

    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
        let LocalState { state, layout: _ } = self;
        state.snapshot(ctx)
    }
}

impl_stable_hash_for!(struct LocalState<'tcx> {
    state,
    layout -> _,
});

impl<'a, 'b, 'mir, 'tcx: 'a+'mir> SnapshotContext<'b>
    for Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>
{
    fn resolve(&'b self, id: &AllocId) -> Option<&'b Allocation> {
        self.get(*id).ok()
    }
}

/// The virtual machine state during const-evaluation at a given point in time.
/// We assume the `CompileTimeInterpreter` has no interesting extra state that
/// is worth considering here.
struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir> {
    memory: Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
    stack: Vec<Frame<'mir, 'tcx>>,
}

impl<'a, 'mir, 'tcx: 'a + 'mir> EvalSnapshot<'a, 'mir, 'tcx>
{
    fn new(
        memory: &Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
        stack: &[Frame<'mir, 'tcx>]
    ) -> Self {
        EvalSnapshot {
            memory: memory.clone(),
            stack: stack.into(),
        }
    }

    // Used to compare two snapshots
    fn snapshot(&'b self)
        -> Vec<FrameSnapshot<'b, 'tcx>>
    {
        // Start with the stack, iterate and recursively snapshot
        self.stack.iter().map(|frame| frame.snapshot(&self.memory)).collect()
    }

}

impl<'a, 'mir, 'tcx> Hash for EvalSnapshot<'a, 'mir, 'tcx>
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        // Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2)
        let mut hcx = self.memory.tcx.get_stable_hashing_context();
        let mut hasher = StableHasher::<u64>::new();
        self.hash_stable(&mut hcx, &mut hasher);
        hasher.finish().hash(state)
    }
}

impl_stable_hash_for!(impl<'tcx, 'b, 'mir> for struct EvalSnapshot<'b, 'mir, 'tcx> {
    // Not hashing memory: Avoid hashing memory all the time during execution
    memory -> _,
    stack,
});

impl<'a, 'mir, 'tcx> Eq for EvalSnapshot<'a, 'mir, 'tcx>
{}

impl<'a, 'mir, 'tcx> PartialEq for EvalSnapshot<'a, 'mir, 'tcx>
{
    fn eq(&self, other: &Self) -> bool {
        // FIXME: This looks to be a *ridicolously expensive* comparison operation.
        // Doesn't this make tons of copies?  Either `snapshot` is very badly named,
        // or it does!
        self.snapshot() == other.snapshot()
    }
}
<|endoftext|>


<commit_before>//! Validates the MIR to ensure that invariants are upheld.

use super::{MirPass, MirSource};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::{
    mir::{
        BasicBlock, Body, Location, Operand, Rvalue, Statement, StatementKind, Terminator,
        TerminatorKind,
    },
    ty::{self, ParamEnv, TyCtxt},
};
use rustc_span::{def_id::DefId, Span, DUMMY_SP};

pub struct Validator {
    /// Describes at which point in the pipeline this validation is happening.
    pub when: String,
}

impl<'tcx> MirPass<'tcx> for Validator {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
        let def_id = source.def_id();
        let param_env = tcx.param_env(def_id);
        TypeChecker { when: &self.when, def_id, body, tcx, param_env }.visit_body(body);
    }
}

struct TypeChecker<'a, 'tcx> {
    when: &'a str,
    def_id: DefId,
    body: &'a Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ParamEnv<'tcx>,
}

impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
    fn fail(&self, span: Span, msg: impl AsRef<str>) {
        // We use `delay_span_bug` as we might see broken MIR when other errors have already
        // occurred.
        self.tcx.sess.diagnostic().delay_span_bug(
            span,
            &format!("broken MIR in {:?} ({}): {}", self.def_id, self.when, msg.as_ref()),
        );
    }

    fn check_bb(&self, span: Span, bb: BasicBlock) {
        if self.body.basic_blocks().get(bb).is_none() {
            self.fail(span, format!("encountered jump to invalid basic block {:?}", bb))
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
        // `Operand::Copy` is only supposed to be used with `Copy` types.
        if let Operand::Copy(place) = operand {
            let ty = place.ty(&self.body.local_decls, self.tcx).ty;
            let span = self.body.source_info(location).span;

            if !ty.is_copy_modulo_regions(self.tcx, self.param_env, span) {
                self.fail(span, format!("`Operand::Copy` with non-`Copy` type {}", ty));
            }
        }

        self.super_operand(operand, location);
    }

    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
        // The sides of an assignment must not alias. Currently this just checks whether the places
        // are identical.
        if let StatementKind::Assign(box (dest, rvalue)) = &statement.kind {
            match rvalue {
                Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) => {
                    if dest == src {
                        self.fail(
                            DUMMY_SP,
                            format!(
                                "encountered `Assign` statement with overlapping memory at {:?}",
                                location
                            ),
                        );
                    }
                }
                _ => {}
            }
        }
    }

    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _location: Location) {
        match &terminator.kind {
            TerminatorKind::Goto { target } => {
                self.check_bb(terminator.source_info.span, *target);
            }
            TerminatorKind::SwitchInt { targets, values, .. } => {
                if targets.len() != values.len() + 1 {
                    self.fail(
                        terminator.source_info.span,
                        format!(
                            "encountered `SwitchInt` terminator with {} values, but {} targets (should be values+1)",
                            values.len(),
                            targets.len(),
                        ),
                    );
                }
                for target in targets {
                    self.check_bb(terminator.source_info.span, *target);
                }
            }
            TerminatorKind::Drop { target, unwind, .. } => {
                self.check_bb(terminator.source_info.span, *target);
                if let Some(unwind) = unwind {
                    self.check_bb(terminator.source_info.span, *unwind);
                }
            }
            TerminatorKind::DropAndReplace { target, unwind, .. } => {
                self.check_bb(terminator.source_info.span, *target);
                if let Some(unwind) = unwind {
                    self.check_bb(terminator.source_info.span, *unwind);
                }
            }
            TerminatorKind::Call { func, destination, cleanup, .. } => {
                let func_ty = func.ty(&self.body.local_decls, self.tcx);
                match func_ty.kind {
                    ty::FnPtr(..) | ty::FnDef(..) => {}
                    _ => self.fail(
                        terminator.source_info.span,
                        format!("encountered non-callable type {} in `Call` terminator", func_ty),
                    ),
                }
                if let Some((_, target)) = destination {
                    self.check_bb(terminator.source_info.span, *target);
                }
                if let Some(cleanup) = cleanup {
                    self.check_bb(terminator.source_info.span, *cleanup);
                }
            }
            TerminatorKind::Assert { cond, target, cleanup, .. } => {
                let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
                if cond_ty != self.tcx.types.bool {
                    self.fail(
                        terminator.source_info.span,
                        format!(
                            "encountered non-boolean condition of type {} in `Assert` terminator",
                            cond_ty
                        ),
                    );
                }
                self.check_bb(terminator.source_info.span, *target);
                if let Some(cleanup) = cleanup {
                    self.check_bb(terminator.source_info.span, *cleanup);
                }
            }
            TerminatorKind::Yield { resume, drop, .. } => {
                self.check_bb(terminator.source_info.span, *resume);
                if let Some(drop) = drop {
                    self.check_bb(terminator.source_info.span, *drop);
                }
            }
            TerminatorKind::FalseEdges { real_target, imaginary_target } => {
                self.check_bb(terminator.source_info.span, *real_target);
                self.check_bb(terminator.source_info.span, *imaginary_target);
            }
            TerminatorKind::FalseUnwind { real_target, unwind } => {
                self.check_bb(terminator.source_info.span, *real_target);
                if let Some(unwind) = unwind {
                    self.check_bb(terminator.source_info.span, *unwind);
                }
            }
            TerminatorKind::InlineAsm { destination, .. } => {
                if let Some(destination) = destination {
                    self.check_bb(terminator.source_info.span, *destination);
                }
            }
            // Nothing to validate for these.
            TerminatorKind::Resume
            | TerminatorKind::Abort
            | TerminatorKind::Return
            | TerminatorKind::Unreachable
            | TerminatorKind::GeneratorDrop => {}
        }
    }
}
<commit_msg>always print MIR Location when validator finds a problem<commit_after>//! Validates the MIR to ensure that invariants are upheld.

use super::{MirPass, MirSource};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::{
    mir::{
        BasicBlock, Body, Location, Operand, Rvalue, Statement, StatementKind, Terminator,
        TerminatorKind,
    },
    ty::{self, ParamEnv, TyCtxt},
};
use rustc_span::def_id::DefId;

pub struct Validator {
    /// Describes at which point in the pipeline this validation is happening.
    pub when: String,
}

impl<'tcx> MirPass<'tcx> for Validator {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
        let def_id = source.def_id();
        let param_env = tcx.param_env(def_id);
        TypeChecker { when: &self.when, def_id, body, tcx, param_env }.visit_body(body);
    }
}

struct TypeChecker<'a, 'tcx> {
    when: &'a str,
    def_id: DefId,
    body: &'a Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ParamEnv<'tcx>,
}

impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
    fn fail(&self, location: Location, msg: impl AsRef<str>) {
        let span = self.body.source_info(location).span;
        // We use `delay_span_bug` as we might see broken MIR when other errors have already
        // occurred.
        self.tcx.sess.diagnostic().delay_span_bug(
            span,
            &format!(
                "broken MIR in {:?} ({}) at {:?}:\n{}",
                self.def_id,
                self.when,
                location,
                msg.as_ref()
            ),
        );
    }

    fn check_bb(&self, location: Location, bb: BasicBlock) {
        if self.body.basic_blocks().get(bb).is_none() {
            self.fail(location, format!("encountered jump to invalid basic block {:?}", bb))
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
        // `Operand::Copy` is only supposed to be used with `Copy` types.
        if let Operand::Copy(place) = operand {
            let ty = place.ty(&self.body.local_decls, self.tcx).ty;
            let span = self.body.source_info(location).span;

            if !ty.is_copy_modulo_regions(self.tcx, self.param_env, span) {
                self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
            }
        }

        self.super_operand(operand, location);
    }

    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
        // The sides of an assignment must not alias. Currently this just checks whether the places
        // are identical.
        if let StatementKind::Assign(box (dest, rvalue)) = &statement.kind {
            match rvalue {
                Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) => {
                    if dest == src {
                        self.fail(
                            location,
                            "encountered `Assign` statement with overlapping memory",
                        );
                    }
                }
                _ => {}
            }
        }
    }

    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        match &terminator.kind {
            TerminatorKind::Goto { target } => {
                self.check_bb(location, *target);
            }
            TerminatorKind::SwitchInt { targets, values, .. } => {
                if targets.len() != values.len() + 1 {
                    self.fail(
                        location,
                        format!(
                            "encountered `SwitchInt` terminator with {} values, but {} targets (should be values+1)",
                            values.len(),
                            targets.len(),
                        ),
                    );
                }
                for target in targets {
                    self.check_bb(location, *target);
                }
            }
            TerminatorKind::Drop { target, unwind, .. } => {
                self.check_bb(location, *target);
                if let Some(unwind) = unwind {
                    self.check_bb(location, *unwind);
                }
            }
            TerminatorKind::DropAndReplace { target, unwind, .. } => {
                self.check_bb(location, *target);
                if let Some(unwind) = unwind {
                    self.check_bb(location, *unwind);
                }
            }
            TerminatorKind::Call { func, destination, cleanup, .. } => {
                let func_ty = func.ty(&self.body.local_decls, self.tcx);
                match func_ty.kind {
                    ty::FnPtr(..) | ty::FnDef(..) => {}
                    _ => self.fail(
                        location,
                        format!("encountered non-callable type {} in `Call` terminator", func_ty),
                    ),
                }
                if let Some((_, target)) = destination {
                    self.check_bb(location, *target);
                }
                if let Some(cleanup) = cleanup {
                    self.check_bb(location, *cleanup);
                }
            }
            TerminatorKind::Assert { cond, target, cleanup, .. } => {
                let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
                if cond_ty != self.tcx.types.bool {
                    self.fail(
                        location,
                        format!(
                            "encountered non-boolean condition of type {} in `Assert` terminator",
                            cond_ty
                        ),
                    );
                }
                self.check_bb(location, *target);
                if let Some(cleanup) = cleanup {
                    self.check_bb(location, *cleanup);
                }
            }
            TerminatorKind::Yield { resume, drop, .. } => {
                self.check_bb(location, *resume);
                if let Some(drop) = drop {
                    self.check_bb(location, *drop);
                }
            }
            TerminatorKind::FalseEdges { real_target, imaginary_target } => {
                self.check_bb(location, *real_target);
                self.check_bb(location, *imaginary_target);
            }
            TerminatorKind::FalseUnwind { real_target, unwind } => {
                self.check_bb(location, *real_target);
                if let Some(unwind) = unwind {
                    self.check_bb(location, *unwind);
                }
            }
            TerminatorKind::InlineAsm { destination, .. } => {
                if let Some(destination) = destination {
                    self.check_bb(location, *destination);
                }
            }
            // Nothing to validate for these.
            TerminatorKind::Resume
            | TerminatorKind::Abort
            | TerminatorKind::Return
            | TerminatorKind::Unreachable
            | TerminatorKind::GeneratorDrop => {}
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::random;
use std::io::BufferedReader;
use std::io;

fn main() {
    println!("I'm thinking of a number between 1 and 100. Can you guess it?");
    let x = random::<int>();
    let mut reader = BufferedReader::new(io::stdin());
    while true {
        let line_result = reader.read_line();
        if line_result.is_ok() {
            let line = line_result.unwrap();
            let num = from_str::<int>(line.slice_to(line.len() - 1));
            match num {
                Some(number_string) => println!("Well, it was a number."),
                None                => println!("Doesn't count.")
            }
        }
        else {
            println!("An error occurred.");
            break;
        }
    }
}
<commit_msg>Interesting to note that this does not work.<commit_after>extern crate rand;

use rand::random;
use std::io::BufferedReader;
use std::io;

fn main() {
    println!("I'm thinking of a number between 1 and 100. Can you guess it?");
    let x = random::<int>();
    let mut reader = BufferedReader::new(io::stdin());
    while true {
        let line_result = reader.read_line();
        if line_result.is_ok() {
            let line = line_result.unwrap();
            let num = from_str::<int>(line.slice_to(line.len() - 1));
            match num {
                Some(x) => break,
                Some(_number_string) => println!("Well, it was a number."),
                None                 => println!("Doesn't count.")
            }
        }
        else {
            println!("An error occurred.");
            break;
        }
    }
}
<|endoftext|>