From d8965fae9231d13690d736bc090be15e95ee5aef Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 19 Aug 2024 20:08:37 +0200 Subject: [PATCH] Handle misplaced options better in the standalone CLI. --- .../ectester/common/cli/ParserOptions.java | 6 +--- .../crcs/ectester/common/cli/TreeParser.java | 36 ++++++++++--------- .../standalone/ECTesterStandalone.java | 27 +++++++++----- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/cli/ParserOptions.java b/common/src/main/java/cz/crcs/ectester/common/cli/ParserOptions.java index 7300cbb9..96dcd012 100644 --- a/common/src/main/java/cz/crcs/ectester/common/cli/ParserOptions.java +++ b/common/src/main/java/cz/crcs/ectester/common/cli/ParserOptions.java @@ -11,13 +11,9 @@ public class ParserOptions { private Options options; private String description; - public ParserOptions(CommandLineParser parser, Options options) { + public ParserOptions(CommandLineParser parser, Options options, String description) { this.parser = parser; this.options = options; - } - - public ParserOptions(CommandLineParser parser, Options options, String description) { - this(parser, options); this.description = description; } diff --git a/common/src/main/java/cz/crcs/ectester/common/cli/TreeParser.java b/common/src/main/java/cz/crcs/ectester/common/cli/TreeParser.java index 657318da..1f2399a7 100644 --- a/common/src/main/java/cz/crcs/ectester/common/cli/TreeParser.java +++ b/common/src/main/java/cz/crcs/ectester/common/cli/TreeParser.java @@ -52,9 +52,12 @@ public TreeCommandLine parse(Options options, String[] arguments, boolean stopAt public TreeCommandLine parse(Options options, String[] arguments, Properties properties, boolean stopAtNonOption) throws ParseException { DefaultParser thisParser = new DefaultParser(); CommandLine cli = thisParser.parse(options, arguments, properties, true); + //System.err.println("arguments " + Arrays.toString(arguments)); + //System.err.println("args " + Arrays.toString(args.stream().map(Argument::getName).collect(Collectors.toList()).toArray())); CommandLine subCli = null; String[] cliArgs = cli.getArgs(); + //System.err.println(Arrays.toString(cliArgs)); String sub = null; if (cliArgs.length != 0) { sub = cliArgs[0]; @@ -74,6 +77,7 @@ public TreeCommandLine parse(Options options, String[] arguments, Properties pro if (matches.size() == 1) { sub = matches.get(0); ParserOptions subparser = parsers.get(sub); + //System.err.println("found sub ->" + sub); String[] remainingArgs = new String[cliArgs.length - 1]; System.arraycopy(cliArgs, 1, remainingArgs, 0, cliArgs.length - 1); subCli = subparser.getParser().parse(subparser.getOptions(), remainingArgs, true); @@ -92,37 +96,35 @@ public TreeCommandLine parse(Options options, String[] arguments, Properties pro if (subCli instanceof TreeCommandLine) { TreeCommandLine subTreeCli = (TreeCommandLine) subCli; - - TreeCommandLine lastCli = subTreeCli; - while (lastCli.getNext() != null) { - lastCli = lastCli.getNext(); - } - - if (lastCli.getArgs().length < requiredArgs) { - throw new MissingArgumentException("Not enough arguments: " + reqArgs); - } - //else if (lastCli.getArgs().length > maxArgs) { - // throw new MissingArgumentException("Too many arguments."); - //} - subTreeCli.setName(sub); return new TreeCommandLine(cli, subTreeCli); } else if (subCli != null) { + //System.err.println("subCli " + subCli.getArgs().length + " maxArgs " + maxArgs); if (subCli.getArgs().length < requiredArgs) { throw new MissingArgumentException("Not enough arguments: " + reqArgs); } else if (subCli.getArgs().length > maxArgs) { - throw new MissingArgumentException("Too many arguments."); + for (String arg : subCli.getArgs()) { + if (arg.startsWith("-")) { + throw new UnrecognizedOptionException("Option " + arg + " not recognized."); + } + } + throw new MissingArgumentException("Too many arguments: " + Arrays.toString(cliArgs)); } TreeCommandLine subTreeCli = new TreeCommandLine(sub, subCli, null); return new TreeCommandLine(cli, subTreeCli); } else { + //System.err.println("cliArgs " + cliArgs.length + " maxArgs " + maxArgs); if (cliArgs.length < requiredArgs) { throw new MissingArgumentException("Not enough arguments: " + reqArgs); + } else if (cliArgs.length > maxArgs) { + for (String arg : cliArgs) { + if (arg.startsWith("-")) { + throw new UnrecognizedOptionException("Option " + arg + " not recognized."); + } + } + throw new MissingArgumentException("Too many arguments: " + Arrays.toString(cliArgs)); } - //else if (cliArgs.length > maxArgs) { - // throw new MissingArgumentException("Too many arguments."); - //} return new TreeCommandLine(cli, null); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java index 04537f0b..1b56ec67 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -256,7 +256,8 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException { testOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build()); List testArgs = new LinkedList<>(); testArgs.add(new Argument("test-suite", "The test suite to run.", true)); - ParserOptions test = new ParserOptions(new TreeParser(Collections.emptyMap(), true, testArgs), testOpts, "Test a library."); + testArgs.add(new Argument("lib", "What library to use.", true)); + ParserOptions test = new ParserOptions(new TreeParser(Collections.emptyMap(), false, testArgs), testOpts, "Test a library."); actions.put("test", test); Options ecdhOpts = new Options(); @@ -273,7 +274,9 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException { ecdhOpts.addOption(Option.builder().longOpt("fixed-private").desc("Perform ECDH with fixed private key.").build()); ecdhOpts.addOptionGroup(privateKey); ecdhOpts.addOption(Option.builder().longOpt("fixed-public").desc("Perform ECDH with fixed public key.").build()); - ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts, "Perform EC based KeyAgreement."); + List ecdhArgs = new LinkedList<>(); + ecdhArgs.add(new Argument("lib", "What library to use.", true)); + ParserOptions ecdh = new ParserOptions(new TreeParser(Collections.emptyMap(), false, ecdhArgs), ecdhOpts, "Perform EC based KeyAgreement."); actions.put("ecdh", ecdh); Options ecdsaOpts = new Options(); @@ -289,7 +292,9 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException { ecdsaOpts.addOption(Option.builder("t").longOpt("type").desc("Set Signature object [type].").hasArg().argName("type").optionalArg(false).build()); ecdsaOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDSA [amount] times.").build()); ecdsaOpts.addOptionGroup(ecdsaMessage); - ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts, "Perform EC based Signature."); + List ecdsaArgs = new LinkedList<>(); + ecdsaArgs.add(new Argument("lib", "What library to use.", true)); + ParserOptions ecdsa = new ParserOptions(new TreeParser(Collections.emptyMap(), false, ecdsaArgs), ecdsaOpts, "Perform EC based Signature."); actions.put("ecdsa", ecdsa); Options generateOpts = new Options(); @@ -301,14 +306,18 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException { generateOpts.addOption(prngSeed); generateOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Generate [amount] of EC keys.").build()); generateOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPairGenerator object [type].").build()); - ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts, "Generate EC keypairs."); + List generateArgs = new LinkedList<>(); + generateArgs.add(new Argument("lib", "What library to use.", true)); + ParserOptions generate = new ParserOptions(new TreeParser(Collections.emptyMap(), false, generateArgs), generateOpts, "Generate EC keypairs."); actions.put("generate", generate); Options exportOpts = new Options(); exportOpts.addOption(bits); exportOpts.addOption(outputRaw); exportOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPair object [type].").build()); - ParserOptions export = new ParserOptions(new DefaultParser(), exportOpts, "Export default curve parameters."); + List exportArgs = new LinkedList<>(); + exportArgs.add(new Argument("lib", "What library to use.", true)); + ParserOptions export = new ParserOptions(new TreeParser(Collections.emptyMap(), false, exportArgs), exportOpts, "Export default curve parameters."); actions.put("export", export); Options listDataOpts = new Options(); @@ -318,7 +327,9 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException { actions.put("list-data", listData); Options listLibsOpts = new Options(); - ParserOptions listLibs = new ParserOptions(new DefaultParser(), listLibsOpts, "List supported libraries."); + List listLibsArgs = new LinkedList<>(); + listLibsArgs.add(new Argument("lib", "What library to use.", false)); + ParserOptions listLibs = new ParserOptions(new TreeParser(Collections.emptyMap(), false, listLibsArgs), listLibsOpts, "List supported libraries."); actions.put("list-libs", listLibs); Options listSuitesOpts = new Options(); @@ -329,9 +340,7 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException { ParserOptions listIdents = new ParserOptions(new DefaultParser(), listIdentsOpts, "List KeyPairGenerator, KeyAgreement and Signature types."); actions.put("list-types", listIdents); - List baseArgs = new LinkedList<>(); - baseArgs.add(new Argument("lib", "What library to use.", false)); - optParser = new TreeParser(actions, false, baseArgs); + optParser = new TreeParser(actions, false); opts.addOption(Option.builder("V").longOpt("version").desc("Print version info.").build()); opts.addOption(Option.builder("h").longOpt("help").desc("Print help(about ).").hasArg().argName("command").optionalArg(true).build());