gen_config should fail with misaligned integers fix #1115

This commit is contained in:
rusefi 2020-02-02 13:24:32 -05:00
parent c2e02cc235
commit a62340b8b9
6 changed files with 69 additions and 29 deletions

Binary file not shown.

View File

@ -11,6 +11,7 @@
<mkdir dir="build/classes"/>
<javac
source="${javac.source}"
debug="true"
target="${javac.target}"
destdir="build/classes"
classpath="lib/junit.jar:lib/annotations.jar:lib/snakeyaml.jar">

View File

@ -54,6 +54,7 @@ public class ConfigStructure {
* we make alignment decision based on C fields since we expect iteration and non-iteration fields
* to match in size
*/
totalSize = 0;
for (int i = 0; i < cFields.size(); i++) {
ConfigField cf = cFields.get(i);
ConfigField next = i == cFields.size() - 1 ? ConfigField.VOID : cFields.get(i + 1);
@ -64,7 +65,7 @@ public class ConfigStructure {
int fillSize = totalSize % 4 == 0 ? 0 : 4 - (totalSize % 4);
if (fillSize != 0) {
ConfigField fill = new ConfigField(state, "alignmentFill", "need 4 byte alignment",
ConfigField fill = new ConfigField(state, "alignmentFill_at_" + totalSize, "need 4 byte alignment",
"" + fillSize,
TypesHelper.UINT8_T, fillSize, null, false, false, null, -1);
addBoth(fill);

View File

@ -95,6 +95,19 @@ public class ReaderState {
}
}
private void handleEndStruct(List<ConfigurationConsumer> consumers) throws IOException {
if (stack.isEmpty())
throw new IllegalStateException("Unexpected end_struct");
ConfigStructure structure = stack.pop();
SystemOut.println("Ending structure " + structure.getName());
structure.addAlignmentFill(this);
structures.put(structure.getName(), structure);
for (ConfigurationConsumer consumer : consumers)
consumer.handleEndStruct(structure);
}
public void readBufferedReader(BufferedReader definitionReader, List<ConfigurationConsumer> consumers) throws IOException {
for (ConfigurationConsumer consumer : consumers)
consumer.startFile();
@ -114,7 +127,7 @@ public class ReaderState {
handleStartStructure(this, line.substring(STRUCT_NO_PREFIX.length()), false);
} else if (line.startsWith(END_STRUCT)) {
addBitPadding();
handleEndStruct(this, consumers);
this.handleEndStruct(consumers);
} else if (line.startsWith(BIT)) {
handleBitLine(this, line);
@ -128,6 +141,8 @@ public class ReaderState {
*/
ConfigDefinition.processDefine(line.substring(DEFINE.length()).trim());
} else {
if (stack.isEmpty())
throw new IllegalStateException("Expected to be within structure");
addBitPadding();
processField(this, line);
}
@ -172,19 +187,6 @@ public class ReaderState {
SystemOut.println("Starting structure " + structure.getName());
}
private static void handleEndStruct(ReaderState state, List<ConfigurationConsumer> consumers) throws IOException {
if (state.stack.isEmpty())
throw new IllegalStateException("Unexpected end_struct");
ConfigStructure structure = state.stack.pop();
SystemOut.println("Ending structure " + structure.getName());
structure.addAlignmentFill(state);
state.structures.put(structure.getName(), structure);
for (ConfigurationConsumer consumer : consumers)
consumer.handleEndStruct(structure);
}
private static void processField(ReaderState state, String line) {
ConfigField cf = ConfigField.parse(state, line);
@ -195,6 +197,15 @@ public class ReaderState {
throw new IllegalStateException(cf.getName() + ": Not enclosed in a struct");
ConfigStructure structure = state.stack.peek();
Integer getPrimitiveSize = TypesHelper.getPrimitiveSize(cf.getType());
if (getPrimitiveSize != null && getPrimitiveSize % 4 == 0) {
SystemOut.println("Need to align before " + cf.getName());
structure.addAlignmentFill(state);
} else {
// adding a structure instance - had to be aligned
// todo? structure.addAlignmentFill(state);
}
if (cf.isIterate()) {
structure.addC(cf);
for (int i = 1; i <= cf.getArraySize(); i++) {

View File

@ -24,6 +24,13 @@ public class TypesHelper {
return state.structures.get(type).totalSize;
if (state != null && state.tsCustomSize.containsKey(type))
return state.tsCustomSize.get(type);
Integer primitiveSize = getPrimitiveSize(type);
if (primitiveSize != null)
return primitiveSize;
throw new IllegalArgumentException("Unknown type " + type);
}
public static Integer getPrimitiveSize(String type) {
if (isPrimitive1byte(type))
return 1;
if (isPrimitive2byte(type)) {
@ -32,7 +39,7 @@ public class TypesHelper {
if (isPrimitive4byte(type)) {
return 4;
}
throw new IllegalArgumentException("Unknown type " + type);
return null;
}
public static boolean isPrimitive(String type) {

View File

@ -2,6 +2,7 @@ package com.rusefi.test;
import com.rusefi.ConfigField;
import com.rusefi.ReaderState;
import com.rusefi.TypesHelper;
import com.rusefi.VariableRegistry;
import com.rusefi.output.FsioSettingsConsumer;
import com.rusefi.output.JavaFieldsConsumer;
@ -9,7 +10,6 @@ import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Arrays;
@ -33,6 +33,24 @@ public class ConfigFieldParserTest {
}
}
@Test
public void alignFourByteTypes() throws IOException {
// we expect padding before each 4 byte field
String test = "struct pid_s\n" +
"\tint16_t periodMs1;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" +
"\tint periodSec;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" +
"\tint16_t periodMs2;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" +
"\tint periodSec2;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" +
"end_struct\n";
ReaderState state = new ReaderState();
BufferedReader reader = new BufferedReader(new StringReader(test));
JavaFieldsConsumer javaFieldsConsumer = createTestJavaConsumer(state);
state.readBufferedReader(reader, Arrays.asList(javaFieldsConsumer));
assertEquals(16, TypesHelper.getElementSize(state, "pid_s"));
}
@Test
public void testFsioVisible() throws IOException {
{
@ -57,19 +75,9 @@ public class ConfigFieldParserTest {
"end_struct\n" +
"" +
"";
Reader inputString = new StringReader(test);
BufferedReader reader = new BufferedReader(inputString);
JavaFieldsConsumer javaFieldsConsumer = new JavaFieldsConsumer(state) {
@Override
public void startFile() {
}
@Override
public void endFile() {
}
};
BufferedReader reader = new BufferedReader(new StringReader(test));
JavaFieldsConsumer javaFieldsConsumer = createTestJavaConsumer(state);
FsioSettingsConsumer fsioSettingsConsumer = new FsioSettingsConsumer(state) {
@Override
@ -154,6 +162,18 @@ public class ConfigFieldParserTest {
}
}
private JavaFieldsConsumer createTestJavaConsumer(ReaderState state) {
return new JavaFieldsConsumer(state) {
@Override
public void startFile() {
}
@Override
public void endFile() {
}
};
}
@Test
public void testParseLine() {
ReaderState state = new ReaderState();