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"]
|
categories = ["config", "encoding", "parser-implementations"]
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = ['test-suite']
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "alexcrichton/toml-rs" }
|
travis-ci = { repository = "alexcrichton/toml-rs" }
|
||||||
|
|
||||||
|
|
36
src/de.rs
36
src/de.rs
|
@ -197,6 +197,7 @@ enum ErrorKind {
|
||||||
/// Deserialization implementation for TOML.
|
/// Deserialization implementation for TOML.
|
||||||
pub struct Deserializer<'a> {
|
pub struct Deserializer<'a> {
|
||||||
require_newline_after_table: bool,
|
require_newline_after_table: bool,
|
||||||
|
allow_duplciate_after_longer_table: bool,
|
||||||
input: &'a str,
|
input: &'a str,
|
||||||
tokens: Tokenizer<'a>,
|
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
|
// Test to see if we're duplicating our parent's table, and if so
|
||||||
// then this is an error in the toml format
|
// then this is an error in the toml format
|
||||||
if self.cur_parent != pos
|
if self.cur_parent != pos {
|
||||||
&& self.tables[self.cur_parent].header == self.tables[pos].header
|
if self.tables[self.cur_parent].header == self.tables[pos].header {
|
||||||
{
|
let at = self.tables[pos].at;
|
||||||
let at = self.tables[pos].at;
|
let name = self.tables[pos].header.join(".");
|
||||||
let name = self.tables[pos].header.join(".");
|
return Err(self.de.error(at, ErrorKind::DuplicateTable(name)));
|
||||||
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];
|
let table = &mut self.tables[pos];
|
||||||
|
@ -965,6 +978,7 @@ impl<'a> Deserializer<'a> {
|
||||||
tokens: Tokenizer::new(input),
|
tokens: Tokenizer::new(input),
|
||||||
input: input,
|
input: input,
|
||||||
require_newline_after_table: true,
|
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;
|
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> {
|
fn tables(&mut self) -> Result<Vec<Table<'a>>, Error> {
|
||||||
let mut tables = Vec::new();
|
let mut tables = Vec::new();
|
||||||
let mut cur_table = Table {
|
let mut cur_table = Table {
|
||||||
|
|
|
@ -4,7 +4,7 @@ extern crate serde;
|
||||||
use serde::de::Deserialize;
|
use serde::de::Deserialize;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn main() {
|
fn newlines_after_tables() {
|
||||||
let s = "
|
let s = "
|
||||||
[a] foo = 1
|
[a] foo = 1
|
||||||
[[b]] foo = 1
|
[[b]] foo = 1
|
||||||
|
@ -17,3 +17,25 @@ fn main() {
|
||||||
assert_eq!(value["a"]["foo"].as_integer(), Some(1));
|
assert_eq!(value["a"]["foo"].as_integer(), Some(1));
|
||||||
assert_eq!(value["b"][0]["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"));
|
include_str!("invalid/text-before-array-separator.toml"));
|
||||||
test!(text_in_array,
|
test!(text_in_array,
|
||||||
include_str!("invalid/text-in-array.toml"));
|
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