Merge pull request #280 from alexcrichton/fix-duplicate
Fix disallowing duplicate table headers
This commit is contained in:
commit
59d250e309
|
@ -15,6 +15,9 @@ facilitate deserializing and serializing Rust structures.
|
|||
"""
|
||||
categories = ["config", "encoding", "parser-implementations"]
|
||||
|
||||
[workspace]
|
||||
members = ['test-suite']
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "alexcrichton/toml-rs" }
|
||||
|
||||
|
|
36
src/de.rs
36
src/de.rs
|
@ -197,6 +197,7 @@ enum ErrorKind {
|
|||
/// Deserialization implementation for TOML.
|
||||
pub struct Deserializer<'a> {
|
||||
require_newline_after_table: bool,
|
||||
allow_duplciate_after_longer_table: bool,
|
||||
input: &'a str,
|
||||
tokens: Tokenizer<'a>,
|
||||
}
|
||||
|
@ -335,12 +336,24 @@ impl<'de, 'b> de::MapAccess<'de> for MapVisitor<'de, 'b> {
|
|||
|
||||
// Test to see if we're duplicating our parent's table, and if so
|
||||
// then this is an error in the toml format
|
||||
if self.cur_parent != pos
|
||||
&& self.tables[self.cur_parent].header == self.tables[pos].header
|
||||
{
|
||||
let at = self.tables[pos].at;
|
||||
let name = self.tables[pos].header.join(".");
|
||||
return Err(self.de.error(at, ErrorKind::DuplicateTable(name)));
|
||||
if self.cur_parent != pos {
|
||||
if self.tables[self.cur_parent].header == self.tables[pos].header {
|
||||
let at = self.tables[pos].at;
|
||||
let name = self.tables[pos].header.join(".");
|
||||
return Err(self.de.error(at, ErrorKind::DuplicateTable(name)));
|
||||
}
|
||||
|
||||
// If we're here we know we should share the same prefix, and if
|
||||
// the longer table was defined first then we want to narrow
|
||||
// down our parent's length if possible to ensure that we catch
|
||||
// duplicate tables defined afterwards.
|
||||
if !self.de.allow_duplciate_after_longer_table {
|
||||
let parent_len = self.tables[self.cur_parent].header.len();
|
||||
let cur_len = self.tables[pos].header.len();
|
||||
if cur_len < parent_len {
|
||||
self.cur_parent = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let table = &mut self.tables[pos];
|
||||
|
@ -965,6 +978,7 @@ impl<'a> Deserializer<'a> {
|
|||
tokens: Tokenizer::new(input),
|
||||
input: input,
|
||||
require_newline_after_table: true,
|
||||
allow_duplciate_after_longer_table: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,6 +1000,16 @@ impl<'a> Deserializer<'a> {
|
|||
self.require_newline_after_table = require;
|
||||
}
|
||||
|
||||
/// Historical versions of toml-rs accidentally allowed a duplicate table
|
||||
/// header after a longer table header was previously defined. This is
|
||||
/// invalid according to the TOML spec, however.
|
||||
///
|
||||
/// This option can be set to `true` (the default is `false`) to emulate
|
||||
/// this behavior for backwards compatibility with older toml-rs versions.
|
||||
pub fn set_allow_duplicate_after_longer_table(&mut self, allow: bool) {
|
||||
self.allow_duplciate_after_longer_table = allow;
|
||||
}
|
||||
|
||||
fn tables(&mut self) -> Result<Vec<Table<'a>>, Error> {
|
||||
let mut tables = Vec::new();
|
||||
let mut cur_table = Table {
|
||||
|
|
|
@ -4,7 +4,7 @@ extern crate serde;
|
|||
use serde::de::Deserialize;
|
||||
|
||||
#[test]
|
||||
fn main() {
|
||||
fn newlines_after_tables() {
|
||||
let s = "
|
||||
[a] foo = 1
|
||||
[[b]] foo = 1
|
||||
|
@ -17,3 +17,25 @@ fn main() {
|
|||
assert_eq!(value["a"]["foo"].as_integer(), Some(1));
|
||||
assert_eq!(value["b"][0]["foo"].as_integer(), Some(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn allow_duplicate_after_longer() {
|
||||
let s = "
|
||||
[dependencies.openssl-sys]
|
||||
version = 1
|
||||
|
||||
[dependencies]
|
||||
libc = 1
|
||||
|
||||
[dependencies]
|
||||
bitflags = 1
|
||||
";
|
||||
assert!(s.parse::<toml::Value>().is_err());
|
||||
|
||||
let mut d = toml::de::Deserializer::new(s);
|
||||
d.set_allow_duplicate_after_longer_table(true);
|
||||
let value = toml::Value::deserialize(&mut d).unwrap();
|
||||
assert_eq!(value["dependencies"]["openssl-sys"]["version"].as_integer(), Some(1));
|
||||
assert_eq!(value["dependencies"]["libc"].as_integer(), Some(1));
|
||||
assert_eq!(value["dependencies"]["bitflags"].as_integer(), Some(1));
|
||||
}
|
||||
|
|
|
@ -96,3 +96,5 @@ test!(text_before_array_separator,
|
|||
include_str!("invalid/text-before-array-separator.toml"));
|
||||
test!(text_in_array,
|
||||
include_str!("invalid/text-in-array.toml"));
|
||||
test!(duplicate_table,
|
||||
include_str!("invalid/duplicate-table.toml"));
|
||||
|
|
8
test-suite/tests/invalid/duplicate-table.toml
Normal file
8
test-suite/tests/invalid/duplicate-table.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[dependencies.openssl-sys]
|
||||
version = "0.5.2"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.1"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.1.1"
|
Loading…
Reference in a new issue