From 96d028ce004f5b4581997fd1d1a0ccfa87d67ea3 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 11 Oct 2024 12:22:21 -0700 Subject: Fix a null-check bug --- .../src/main/java/com/seaofnodes/simple/Parser.java | 2 +- .../test/java/com/seaofnodes/simple/Chapter13Test.java | 18 ++++++++++++++++++ .../src/main/java/com/seaofnodes/simple/Parser.java | 2 +- .../test/java/com/seaofnodes/simple/Chapter13Test.java | 18 ++++++++++++++++++ .../src/main/java/com/seaofnodes/simple/Parser.java | 6 +++--- .../test/java/com/seaofnodes/simple/Chapter13Test.java | 18 ++++++++++++++++++ 6 files changed, 59 insertions(+), 5 deletions(-) diff --git a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java index 53448e4d..71bd6d02 100644 --- a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java @@ -646,7 +646,7 @@ public class Parser { } Type declaredType = base._fields[idx]._type; - return parsePostfix(new LoadNode(name, alias, declaredType, memAlias(alias), expr).peephole()); + return parsePostfix(new LoadNode(name, alias, declaredType.glb(), memAlias(alias), expr).peephole()); } /** diff --git a/chapter13/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter13/src/test/java/com/seaofnodes/simple/Chapter13Test.java index 3fc5502e..b425fd85 100644 --- a/chapter13/src/test/java/com/seaofnodes/simple/Chapter13Test.java +++ b/chapter13/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -163,4 +163,22 @@ return new S1.s=new S2; StopNode stop = parser.parse().iterate(false); assertEquals("return new S1;", stop.toString()); } + + @Test + public void testcheckNull() { + Parser parser = new Parser( +""" +struct I {int i;} +struct P {I pi;} +P p1 = new P; +P p2 = new P; +p2.pi = new I; +p2.pi.i = 2; +if (arg) p1 = new P; +return p1.pi.i + 1; +"""); + try { parser.parse(false).iterate(); fail(); } + catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); } + } + } diff --git a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java index 417f4295..9e4b9eb6 100644 --- a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java @@ -718,7 +718,7 @@ public class Parser { } Type declaredType = base._fields[idx]._type; - return parsePostfix(new LoadNode(name, alias, declaredType, memAlias(alias), expr).peephole()); + return parsePostfix(new LoadNode(name, alias, declaredType.glb(), memAlias(alias), expr).peephole()); } // zero/sign extend. "i" is limited to either classic unsigned (min==0) or diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java index 62191459..0edb2d51 100644 --- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java +++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -163,4 +163,22 @@ return new S1.s=new S2; StopNode stop = parser.parse().iterate(false); assertEquals("return new S1;", stop.toString()); } + + @Test + public void testcheckNull() { + Parser parser = new Parser( +""" +struct I {int i;} +struct P {I pi;} +P p1 = new P; +P p2 = new P; +p2.pi = new I; +p2.pi.i = 2; +if (arg) p1 = new P; +return p1.pi.i + 1; +"""); + try { parser.parse(false).iterate(); fail(); } + catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); } + } + } diff --git a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java index 012a010e..728aaca7 100644 --- a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java @@ -807,7 +807,7 @@ public class Parser { val = zsMask(val,f._type); Node st = new StoreNode(name, f._alias, f._type, memAlias(f._alias), expr, off, val, false); // Arrays include control, as a proxy for a safety range check. - // Structs dont need this; they only need a NPE check which is + // Structs don't need this; they only need a NPE check which is // done via the type system. if( base.isAry() ) st.setDef(0,ctrl()); memAlias(f._alias, st.peephole()); @@ -815,9 +815,9 @@ public class Parser { } } - Node load = new LoadNode(name, f._alias, f._type, memAlias(f._alias), expr, off); + Node load = new LoadNode(name, f._alias, f._type.glb(), memAlias(f._alias), expr, off); // Arrays include control, as a proxy for a safety range check - // Structs dont need this; they only need a NPE check which is + // Structs don't need this; they only need a NPE check which is // done via the type system. if( base.isAry() ) load.setDef(0,ctrl()); return parsePostfix(load.peephole()); diff --git a/chapter15/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter15/src/test/java/com/seaofnodes/simple/Chapter13Test.java index e8b71820..416aba31 100644 --- a/chapter15/src/test/java/com/seaofnodes/simple/Chapter13Test.java +++ b/chapter15/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -163,4 +163,22 @@ return new S1.s=new S2; StopNode stop = parser.parse().iterate(); assertEquals("return S2;", stop.toString()); } + + @Test + public void testcheckNull() { + Parser parser = new Parser( +""" +struct I {int i;} +struct P {I pi;} +P p1 = new P; +P p2 = new P; +p2.pi = new I; +p2.pi.i = 2; +if (arg) p1 = new P; +return p1.pi.i + 1; +"""); + try { parser.parse(false).iterate(); fail(); } + catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); } + } + } -- cgit v1.2.3