Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  lib.rs   Sprache: unbekannt

 
// Copyright 2015-2016 Mozilla Foundation. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Adapted from third_party/rust/encoding_rs/src/lib.rs, so the
// "top-level directory" in the above notice refers to
// third_party/rust/encoding_rs/.

extern crate encoding_rs;
extern crate nserror;
extern crate nsstring;
extern crate xmldecl;

use encoding_rs::*;
use nserror::*;
use nsstring::*;
use std::slice;

/// Takes `Option<usize>`, the destination string and a value
/// to return on failure and tries to start a bulk write of the
/// destination string with the capacity given by the `usize`
/// wrapped in the first argument. Returns the bulk write
/// handle.
macro_rules! try_start_bulk_write {
    ($needed:expr,
     $dst:ident,
     $ret:expr) => {{
        let needed = match $needed {
            Some(needed) => needed,
            None => {
                return $ret;
            }
        };
        match unsafe { $dst.bulk_write(needed, 0, false) } {
            Err(_) => {
                return $ret;
            }
            Ok(handle) => handle,
        }
    }};
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nsstring(
    encoding: *mut *const Encoding,
    src: *const u8,
    src_len: usize,
    dst: *mut nsAString,
) -> nsresult {
    let (rv, enc) = decode_to_nsstring(&**encoding, slice::from_raw_parts(src, src_len), &mut *dst);
    *encoding = enc as *const Encoding;
    rv
}

pub fn decode_to_nsstring(
    encoding: &'static Encoding,
    src: &[u8],
    dst: &mut nsAString,
) -> (nsresult, &'static Encoding) {
    if let Some((enc, bom_length)) = Encoding::for_bom(src) {
        return (
            decode_to_nsstring_without_bom_handling(enc, &src[bom_length..], dst),
            enc,
        );
    }
    (
        decode_to_nsstring_without_bom_handling(encoding, src, dst),
        encoding,
    )
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nsstring_with_bom_removal(
    encoding: *const Encoding,
    src: *const u8,
    src_len: usize,
    dst: *mut nsAString,
) -> nsresult {
    decode_to_nsstring_with_bom_removal(&*encoding, slice::from_raw_parts(src, src_len), &mut ;*dst)
}

pub fn decode_to_nsstring_with_bom_removal(
    encoding: &'static Encoding,
    src: &[u8],
    dst: &mut nsAString,
) -> nsresult {
    let without_bom = if encoding == UTF_8 && src.starts_with(b"\xEF\xBB\xBF") {
        &src[3..]
    } else if (encoding == UTF_16LE && src.starts_with(b"\xFF\xFE"))
        || (encoding == UTF_16BE && src.starts_with(b"\xFE\xFF"))
    {
        &src[2..]
    } else {
        src
    };
    decode_to_nsstring_without_bom_handling(encoding, without_bom, dst)
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nsstring_without_bom_handling(
    encoding: *const Encoding,
    src: *const u8,
    src_len: usize,
    dst: *mut nsAString,
) -> nsresult {
    decode_to_nsstring_without_bom_handling(
        &*encoding,
        slice::from_raw_parts(src, src_len),
        &mut *dst,
    )
}

pub fn decode_to_nsstring_without_bom_handling(
    encoding: &'static Encoding,
    src: &[u8],
    dst: &mut nsAString,
) -> nsresult {
    let mut decoder = encoding.new_decoder_without_bom_handling();
    let mut handle = try_start_bulk_write!(
        decoder.max_utf16_buffer_length(src.len()),
        dst,
        NS_ERROR_OUT_OF_MEMORY
    );
    let (result, read, written, had_errors) =
        decoder.decode_to_utf16(src, handle.as_mut_slice(), true);
    debug_assert_eq!(result, CoderResult::InputEmpty);
    debug_assert_eq!(read, src.len());
    debug_assert!(written <= handle.as_mut_slice().len());
    let _ = handle.finish(written, true);
    if had_errors {
        return NS_OK_HAD_REPLACEMENTS;
    }
    NS_OK
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nsstring_without_bom_handling_and_without_replacement(
    encoding: *const Encoding,
    src: *const u8,
    src_len: usize,
    dst: *mut nsAString,
) -> nsresult {
    decode_to_nsstring_without_bom_handling_and_without_replacement(
        &*encoding,
        slice::from_raw_parts(src, src_len),
        &mut *dst,
    )
}

pub fn decode_to_nsstring_without_bom_handling_and_without_replacement(
    encoding: &'static Encoding,
    src: &[u8],
    dst: &mut nsAString,
) -> nsresult {
    let mut decoder = encoding.new_decoder_without_bom_handling();
    let mut handle = try_start_bulk_write!(
        decoder.max_utf16_buffer_length(src.len()),
        dst,
        NS_ERROR_OUT_OF_MEMORY
    );
    let (result, read, written) =
        decoder.decode_to_utf16_without_replacement(src, handle.as_mut_slice(), true);
    match result {
        DecoderResult::InputEmpty => {
            debug_assert_eq!(read, src.len());
            debug_assert!(written <= handle.as_mut_slice().len());
            let _ = handle.finish(written, true);
            NS_OK
        }
        DecoderResult::Malformed(_, _) => {
            // Let handle's drop() run
            NS_ERROR_UDEC_ILLEGALINPUT
        }
        DecoderResult::OutputFull => unreachable!(),
    }
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_encode_from_utf16(
    encoding: *mut *const Encoding,
    src: *const u16,
    src_len: usize,
    dst: *mut nsACString,
) -> nsresult {
    let (rv, enc) = encode_from_utf16(&**encoding, slice::from_raw_parts(src, src_len), &mut *dst);
    *encoding = enc as *const Encoding;
    rv
}

pub fn encode_from_utf16(
    encoding: &'static Encoding,
    src: &[u16],
    dst: &mut nsACString,
) -> (nsresult, &'static Encoding) {
    let output_encoding = encoding.output_encoding();
    let mut encoder = output_encoding.new_encoder();
    let mut handle = try_start_bulk_write!(
        encoder.max_buffer_length_from_utf16_if_no_unmappables(src.len()),
        dst,
        (NS_ERROR_OUT_OF_MEMORY, output_encoding)
    );

    let mut total_read = 0;
    let mut total_written = 0;
    let mut total_had_errors = false;
    loop {
        let (result, read, written, had_errors) = encoder.encode_from_utf16(
            &src[total_read..],
            &mut (handle.as_mut_slice())[total_written..],
            true,
        );
        total_read += read;
        total_written += written;
        total_had_errors |= had_errors;
        match result {
            CoderResult::InputEmpty => {
                debug_assert_eq!(total_read, src.len());
                debug_assert!(total_written <= handle.as_mut_slice().len());
                let _ = handle.finish(total_written, true);
                if total_had_errors {
                    return (NS_OK_HAD_REPLACEMENTS, output_encoding);
                }
                return (NS_OK, output_encoding);
            }
            CoderResult::OutputFull => {
                if let Some(needed) = checked_add(
                    total_written,
                    encoder.max_buffer_length_from_utf16_if_no_unmappables(src.len() - total_read),
                ) {
                    if unsafe {
                        handle
                            .restart_bulk_write(needed, total_written, false)
                            .is_ok()
                    } {
                        continue;
                    }
                }
                return (NS_ERROR_OUT_OF_MEMORY, output_encoding);
            }
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nscstring(
    encoding: *mut *const Encoding,
    src: *const nsACString,
    dst: *mut nsACString,
) -> nsresult {
    debug_assert_ne!(src as usize, dst as usize);
    let (rv, enc) = decode_to_nscstring(&**encoding, &*src, &mut *dst);
    *encoding = enc as *const Encoding;
    rv
}

pub fn decode_to_nscstring(
    encoding: &'static Encoding,
    src: &nsACString,
    dst: &mut nsACString,
) -> (nsresult, &'static Encoding) {
    if let Some((enc, bom_length)) = Encoding::for_bom(src) {
        return (
            decode_from_slice_to_nscstring_without_bom_handling(enc, &src[bom_length..], dst, 0),
            enc,
        );
    }
    (
        decode_to_nscstring_without_bom_handling(encoding, src, dst),
        encoding,
    )
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nscstring_with_bom_removal(
    encoding: *const Encoding,
    src: *const nsACString,
    dst: *mut nsACString,
) -> nsresult {
    debug_assert_ne!(src as usize, dst as usize);
    decode_to_nscstring_with_bom_removal(&*encoding, &*src, &mut *dst)
}

pub fn decode_to_nscstring_with_bom_removal(
    encoding: &'static Encoding,
    src: &nsACString,
    dst: &mut nsACString,
) -> nsresult {
    let without_bom = if encoding == UTF_8 && src.starts_with(b"\xEF\xBB\xBF") {
        &src[3..]
    } else if (encoding == UTF_16LE && src.starts_with(b"\xFF\xFE"))
        || (encoding == UTF_16BE && src.starts_with(b"\xFE\xFF"))
    {
        &src[2..]
    } else {
        return decode_to_nscstring_without_bom_handling(encoding, src, dst);
    };
    decode_from_slice_to_nscstring_without_bom_handling(encoding, without_bom, dst, 0)
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nscstring_without_bom_handling(
    encoding: *const Encoding,
    src: *const nsACString,
    dst: *mut nsACString,
) -> nsresult {
    debug_assert_ne!(src as usize, dst as usize);
    decode_to_nscstring_without_bom_handling(&*encoding, &*src, &mut *dst)
}

pub fn decode_to_nscstring_without_bom_handling(
    encoding: &'static Encoding,
    src: &nsACString,
    dst: &mut nsACString,
) -> nsresult {
    let bytes = &src[..];
    let valid_up_to = if encoding == UTF_8 {
        Encoding::utf8_valid_up_to(bytes)
    } else if encoding.is_ascii_compatible() {
        Encoding::ascii_valid_up_to(bytes)
    } else if encoding == ISO_2022_JP {
        Encoding::iso_2022_jp_ascii_valid_up_to(bytes)
    } else {
        return decode_from_slice_to_nscstring_without_bom_handling(encoding, src, dst, 0);
    };
    if valid_up_to == bytes.len() {
        if dst.fallible_assign(src).is_err() {
            return NS_ERROR_OUT_OF_MEMORY;
        }
        return NS_OK;
    }
    decode_from_slice_to_nscstring_without_bom_handling(encoding, src, dst, valid_up_to)
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_from_slice_to_nscstring_without_bom_handling(
    encoding: *const Encoding,
    src: *const u8,
    src_len: usize,
    dst: *mut nsACString,
    already_validated: usize,
) -> nsresult {
    decode_from_slice_to_nscstring_without_bom_handling(
        &*encoding,
        slice::from_raw_parts(src, src_len),
        &mut *dst,
        already_validated,
    )
}

fn decode_from_slice_to_nscstring_without_bom_handling(
    encoding: &'static Encoding,
    src: &[u8],
    dst: &mut nsACString,
    already_validated: usize,
) -> nsresult {
    let bytes = src;
    let mut decoder = encoding.new_decoder_without_bom_handling();
    let mut handle = try_start_bulk_write!(Some(src.len()), dst, NS_ERROR_OUT_OF_MEMORY);

    if already_validated != 0 {
        (handle.as_mut_slice())[..already_validated].copy_from_slice(&bytes[..already_validated]);
    }
    let mut total_read = already_validated;
    let mut total_written = already_validated;
    let mut total_had_errors = false;
    loop {
        let (result, read, written, had_errors) = decoder.decode_to_utf8(
            &bytes[total_read..],
            &mut (handle.as_mut_slice())[total_written..],
            true,
        );
        total_read += read;
        total_written += written;
        total_had_errors |= had_errors;
        match result {
            CoderResult::InputEmpty => {
                debug_assert_eq!(total_read, bytes.len());
                let _ = handle.finish(total_written, true);
                if total_had_errors {
                    return NS_OK_HAD_REPLACEMENTS;
                }
                return NS_OK;
            }
            CoderResult::OutputFull => {
                // Allocate for the worst case. That is, we should come
                // here at most once per invocation of this method.
                if let Some(needed) = checked_add(
                    total_written,
                    decoder.max_utf8_buffer_length(bytes.len() - total_read),
                ) {
                    if unsafe {
                        handle
                            .restart_bulk_write(needed, total_written, false)
                            .is_ok()
                    } {
                        continue;
                    }
                }
                return NS_ERROR_OUT_OF_MEMORY;
            }
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_decode_to_nscstring_without_bom_handling_and_without_replacement(
    encoding: *const Encoding,
    src: *const nsACString,
    dst: *mut nsACString,
) -> nsresult {
    decode_to_nscstring_without_bom_handling_and_without_replacement(&*encoding, &*src, &mut *dst)
}

pub fn decode_to_nscstring_without_bom_handling_and_without_replacement(
    encoding: &'static Encoding,
    src: &nsACString,
    dst: &mut nsACString,
) -> nsresult {
    let bytes = &src[..];
    if encoding == UTF_8 {
        let valid_up_to = Encoding::utf8_valid_up_to(bytes);
        if valid_up_to == bytes.len() {
            if dst.fallible_assign(src).is_err() {
                return NS_ERROR_OUT_OF_MEMORY;
            }
            return NS_OK;
        }
        return NS_ERROR_UDEC_ILLEGALINPUT;
    }
    let valid_up_to = if encoding.is_ascii_compatible() {
        Encoding::ascii_valid_up_to(bytes)
    } else if encoding == ISO_2022_JP {
        Encoding::iso_2022_jp_ascii_valid_up_to(bytes)
    } else {
        0
    };
    if valid_up_to == bytes.len() {
        if dst.fallible_assign(src).is_err() {
            return NS_ERROR_OUT_OF_MEMORY;
        }
        return NS_OK;
    }
    let mut decoder = encoding.new_decoder_without_bom_handling();
    let mut handle = try_start_bulk_write!(
        checked_add(
            valid_up_to,
            decoder.max_utf8_buffer_length_without_replacement(bytes.len() - valid_up_to)
        ),
        dst,
        NS_ERROR_OUT_OF_MEMORY
    );
    let (result, read, written) = {
        let dest = handle.as_mut_slice();
        dest[..valid_up_to].copy_from_slice(&bytes[..valid_up_to]);
        decoder.decode_to_utf8_without_replacement(
            &src[valid_up_to..],
            &mut dest[valid_up_to..],
            true,
        )
    };
    match result {
        DecoderResult::InputEmpty => {
            debug_assert_eq!(valid_up_to + read, src.len());
            debug_assert!(valid_up_to + written <= handle.as_mut_slice().len());
            let _ = handle.finish(valid_up_to + written, true);
            NS_OK
        }
        DecoderResult::Malformed(_, _) => {
            // let handle's drop() run
            NS_ERROR_UDEC_ILLEGALINPUT
        }
        DecoderResult::OutputFull => unreachable!(),
    }
}

#[no_mangle]
pub unsafe extern "C" fn mozilla_encoding_encode_from_nscstring(
    encoding: *mut *const Encoding,
    src: *const nsACString,
    dst: *mut nsACString,
) -> nsresult {
    let (rv, enc) = encode_from_nscstring(&**encoding, &*src, &mut *dst);
    *encoding = enc as *const Encoding;
    rv
}

pub fn encode_from_nscstring(
    encoding: &'static Encoding,
    src: &nsACString,
    dst: &mut nsACString,
) -> (nsresult, &'static Encoding) {
    let output_encoding = encoding.output_encoding();
    let bytes = &src[..];
    if output_encoding == UTF_8 {
        let valid_up_to = Encoding::utf8_valid_up_to(bytes);
        if valid_up_to == bytes.len() {
            if dst.fallible_assign(src).is_err() {
                return (NS_ERROR_OUT_OF_MEMORY, output_encoding);
            }
            return (NS_OK, output_encoding);
        }
        return (NS_ERROR_UDEC_ILLEGALINPUT, output_encoding);
    }
    let valid_up_to = if output_encoding == ISO_2022_JP {
        Encoding::iso_2022_jp_ascii_valid_up_to(bytes)
    } else {
        debug_assert!(output_encoding.is_ascii_compatible());
        Encoding::ascii_valid_up_to(bytes)
    };
    if valid_up_to == bytes.len() {
        if dst.fallible_assign(src).is_err() {
            return (NS_ERROR_OUT_OF_MEMORY, output_encoding);
        }
        return (NS_OK, output_encoding);
    }

    // Encoder requires valid UTF-8. Using std instead of encoding_rs
    // to avoid unsafe blocks.
    let trail = if let Ok(trail) = ::std::str::from_utf8(&bytes[valid_up_to..]) {
        trail
    } else {
        return (NS_ERROR_UDEC_ILLEGALINPUT, output_encoding);
    };

    let mut encoder = output_encoding.new_encoder();
    let mut handle = try_start_bulk_write!(
        checked_add(
            valid_up_to,
            encoder.max_buffer_length_from_utf8_if_no_unmappables(trail.len())
        ),
        dst,
        (NS_ERROR_OUT_OF_MEMORY, output_encoding)
    );

    if valid_up_to != 0 {
        // to_mut() shouldn't fail right after setting length.
        (handle.as_mut_slice())[..valid_up_to].copy_from_slice(&bytes[..valid_up_to]);
    }

    // `total_read` tracks `trail` only but `total_written` tracks the overall situation!
    // This asymmetry is here, because trail is materialized as `str` without resorting
    // to unsafe code here.
    let mut total_read = 0;
    let mut total_written = valid_up_to;
    let mut total_had_errors = false;
    loop {
        let (result, read, written, had_errors) = encoder.encode_from_utf8(
            &trail[total_read..],
            &mut (handle.as_mut_slice())[total_written..],
            true,
        );
        total_read += read;
        total_written += written;
        total_had_errors |= had_errors;
        match result {
            CoderResult::InputEmpty => {
                debug_assert_eq!(valid_up_to + total_read, src.len());
                debug_assert!(total_written <= handle.as_mut_slice().len());
                let _ = handle.finish(total_written, true);
                if total_had_errors {
                    return (NS_OK_HAD_REPLACEMENTS, output_encoding);
                }
                return (NS_OK, output_encoding);
            }
            CoderResult::OutputFull => {
                if let Some(needed) = checked_add(
                    total_written,
                    encoder.max_buffer_length_from_utf8_if_no_unmappables(trail.len() - total_read),
                ) {
                    if unsafe {
                        handle
                            .restart_bulk_write(needed, total_written, false)
                            .is_ok()
                    } {
                        continue;
                    }
                }
                return (NS_ERROR_OUT_OF_MEMORY, output_encoding);
            }
        }
    }
}

#[inline(always)]
fn checked_add(num: usize, opt: Option<usize>) -> Option<usize> {
    if let Some(n) = opt {
        n.checked_add(num)
    } else {
        None
    }
}

// Declared in nsHtml5StreamParser.cpp
#[no_mangle]
pub unsafe extern "C" fn xmldecl_parse(
    buf: *const u8,
    buf_len: usize,
) -> *const encoding_rs::Encoding {
    if let Some(encoding) = xmldecl::parse(std::slice::from_raw_parts(buf, buf_len)) {
        encoding
    } else {
        std::ptr::null()
    }
}

[ Dauer der Verarbeitung: 0.44 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge