Initially, JSword only accepted Major.Minor, converting that into a decimal. That was based on a poor understanding of the CrossWire wiki. That was changed to match SWORD’s 4 part “number” with a minor modification.
JSword will reject any version that doesn’t match the pattern: ^(\d+)(?:.(\d+))?(?:.(\d+))?(?:.(\d+))?$ I think I encoded this to allow pretty much any single non-digit separator. The . will match any single character and \d+ is greedy. So it will accept Karl’s encoding. The wiki on the conf clearly states: “Do not use non-numbers, such as 1.4a” (See: http://wiki.crosswire.org/DevTools:conf_Files <http://wiki.crosswire.org/DevTools:conf_Files>) The conf also documents that the third part should be incremented when only the conf is affected. The first or second when the module is different. Here is JSword's code: /** * Distribution License: * JSword is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License, version 2.1 or later * as published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * The License is available on the internet at: * http://www.gnu.org/copyleft/lgpl.html * or by writing to: * Free Software Foundation, Inc. * 59 Temple Place - Suite 330 * Boston, MA 02111-1307, USA * * © CrossWire Bible Society, 2011 - 2016 * */ package org.crosswire.common.util; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Version is an immutable representation of dotted "number" consisting of 1 to 4 parts. * * <p> * Here is the grammar for version strings: * </p> * <pre> * version ::= major('.'minor('.'micro('.'nano)?)?)? * major ::= [0-9]+ * minor ::= [0-9]+ * micro ::= [0-9]+ * nano ::= [0-9]+ * </pre> * * @see gnu.lgpl.License The GNU Lesser General Public License for details. * @author DM Smith */ public class Version implements Comparable<Version> { public static final Pattern VERSION_PATTERN = Pattern.compile("^(\\d+)(?:.(\\d+))?(?:.(\\d+))?(?:.(\\d+))?$"); /** * Created a version identifier from the specified string. * * @param version String representation of the version identifier. * @throws IllegalArgumentException If <code>version</code> is improperly * formatted. */ public Version(String version) { if (version == null) { throw new IllegalArgumentException("Null version not allowed."); } this.original = version; this.parts = new int[] { -1, -1, -1, -1 }; Matcher matcher = VERSION_PATTERN.matcher(this.original); if (matcher.matches()) { int count = matcher.groupCount(); for (int i = 1; i <= count; i++) { String part = matcher.group(i); if (part == null) { break; } parts[i - 1] = Integer.parseInt(part); } } else { throw new IllegalArgumentException("invalid: " + version); } } /** * Returns the original string representation of this version identifier. * * @return The original string representation of this version identifier. */ @Override public String toString() { return original; } @Override public int hashCode() { return original.hashCode(); } /** * Compares this <code>Version</code> object to another object. * * <p> * A version is considered to be equal to another version if all the * parts are equal.</p> * * @param object The <code>Version</code> object to be compared. * @return true if the two objects are equal. */ @Override public boolean equals(Object object) { if (!(object instanceof Version)) { return false; } Version that = (Version) object; if (that == this) { return true; } for (int i = 0; i < parts.length; i++) { if (parts[i] != that.parts[i]) { return false; } } return true; } /** * Compares this <code>Version</code> object to another object. * * <p> * The comparison considers each of the parts (major, minor, micro, nano) in turn, * comparing like with like. At any point the comparison is not equal, a result is * known. * </p> * * @param object The <code>Version</code> object to be compared. * @return A negative integer, zero, or a positive integer if this object is * less than, equal to, or greater than the specified * <code>Version</code> object. * @throws ClassCastException If the specified object is not a <code>Version</code>. */ public int compareTo(Version object) { if (object == this) { return 0; } for (int i = 0; i < parts.length; i++) { int result = parts[i] - object.parts[i]; if (result != 0) { return result; } } return 0; } private final String original; private final int[] parts; } > On Sep 25, 2018, at 7:07 AM, David Haslam <dfh...@protonmail.com> wrote: > > Thanks Peter, > > We should therefore also encourage Karl to review and update any such modules > in the Xiphos repository. > > The reason I added my aside was that version values are clearly used for > comparison purposes to determine whether a module has been updated. > Version is one of maybe only a few configuration keys upon which calculations > are made. > This logically led me to pose the question about potential buffer overflows, > even though I'm not part of the SWORD coding team. > cf. My awareness of what can be exploited from a buffer overflow or the like > has been honed by 13 years of watching the Security Now! webcasts on twit.tv > > Further aside: How does JSword process the same key? > > David > > Sent from ProtonMail Mobile > > > On Tue, Sep 25, 2018 at 11:54, Peter Von Kaehne <ref...@gmx.net > <mailto:ref...@gmx.net>> wrote: >> I think there are two aspects then - version numbers should be correct in >> current modules. I think the bulk of the modules you listed are Xiphos, not >> CrossWire, but at least one is issued by CrossWire, maybe more. I will fix >> CrossWire's set. >> >> The other is - wrong version numbers should not crash the engine or produce >> unreliable/undefined results. Or at least the engine should go down with a >> decent error message. In essence all places where wrong module conf file >> entries can cause grief in the engine, I guess some level of sanity checking >> should happen - Particularly if we want to encourage other publishers to >> take up offering repositories. >> >> Peter >> >> >> >> > Gesendet: Dienstag, 25. September 2018 um 10:56 Uhr >> > Von: "Jaak Ristioja" <j...@ristioja.ee> >> > An: sword-devel@crosswire.org >> > Betreff: Re: [sword-devel] Module version numbers >> > >> > > Aside: Are there any limits to the number of dot separators in the >> > Version value, or to the number of digits in total or in any part? >> > > Would SWORD crash with a buffer overflow were it to encounter an >> > inordinately long Version? >> > >> > The relevant code to parse the version string is in the SWVersion >> > constructor: >> > >> > SWVersion::SWVersion(const char *version) { >> > char *buf = new char[ strlen(version) + 1 ]; >> > char *tok; >> > major = minor = minor2 = minor3 = -1; >> > >> > strcpy(buf, version); >> > tok = strtok(buf, "."); >> > if (tok) >> > major = atoi(tok); >> > tok = strtok(0, "."); >> > if (tok) >> > minor = atoi(tok); >> > tok = strtok(0, "."); >> > if (tok) >> > minor2 = atoi(tok); >> > tok = strtok(0, "."); >> > if (tok) >> > minor3 = atoi(tok); >> > delete [] buf; >> > } >> > >> > Very long version strings can only crash it if this runs out of memory. >> > Other than that, it will just return an incorrect version. There are no >> > limits to the number of dot separators, but only up to 4 version >> > components separated by dots are actually parsed. AFAIK, the behavior of >> > atoi() is undefined for invalid input. On my system, the results are as >> > follows: >> > >> > "9.1" -> 9.1 >> > "99.1" -> 99.1 >> > "999.1" -> 999.1 >> > "9999.1" -> 9999.1 >> > "99999.1" -> 99999.1 >> > "999999.1" -> 999999.1 >> > "9999999.1" -> 9999999.1 >> > "99999999.1" -> 99999999.1 >> > "999999999.1" -> 999999999.1 >> > "9999999999.1" -> 1410065407.1 >> > "99999999999.1" -> 1215752191.1 >> > "999999999999.1" -> -727379969.1 >> > "9999999999999.1" -> 1316134911.1 >> > "99999999999999.1" -> 276447231.1 >> > "999999999999999.1" -> -1530494977.1 >> > "9999999999999999.1" -> 1874919423.1 >> > "99999999999999999.1" -> 1569325055.1 >> > "999999999999999999.1" -> -1486618625.1 >> > "9999999999999999999.1" -> -1.1 >> > "99999999999999999999.1" -> -1.1 >> > >> > >> > J >> > >> > On 25.09.2018 12:03, David Haslam wrote: >> > > Ignoring the spurious SwordVersion hit, it seems that the string after >> > > the dash is a date in six digit format. >> > > >> > > IMHO, these modules should simply be re-issued with the dates recorded >> > > in the respective History key. >> > > >> > > It's not worth the effort to make the API parse these as they are now. >> > > The dash is a nonconformance to what should be in the Version key. >> > > >> > > Aside: Are there any limits to the number of dot separators in the >> > > Version value, or to the number of digits in total or in any part? >> > > Would SWORD crash with a buffer overflow were it to encounter an >> > > inordinately long Version? >> > > >> > > Best regards, >> > > >> > > David >> > > >> > > Sent from ProtonMail Mobile >> > > >> > > On Tue, Sep 25, 2018 at 09:44, Jaak Ristioja <j...@ristioja.ee> wrote: >> > > >> > >> Hello! >> > >> >> > >> Most modules include version numbers matching the regular expression >> > >> >> > >> ^[0-9]+(.[0-9]+)*$ >> > >> >> > >> However, looking at the .conf files, there are version fields with >> > >> values also containing dashes: >> > >> >> > >> ~/.sword/mods.d $ grep -E 'Version=.*-' * >> > >> 2tgreek.conf:Version=2.7-120109 >> > >> invstrongsrealgreek.conf:Version=1.4-090107 >> > >> jesermons.conf:SwordVersion=2017-05-24 >> > >> strongsrealgreek.conf:Version=1.5-150704 >> > >> tischmorph.conf:Version=2.7-120109 >> > >> >> > >> How should these be interpreted? Should 1.2-3.4 be interpreted as >> > >> (1).(2-3).(4) or (1.2)-(3.4)? It seems that SWVersion interprets such >> > >> as >> > >> just 1.2.4 (without the -3 entirely). >> > >> >> > >> God bless! >> > >> J >> > >> >> > >> _______________________________________________ >> > >> sword-devel mailing list: sword-devel@crosswire.org >> > >> http://www.crosswire.org/mailman/listinfo/sword-devel >> > >> Instructions to unsubscribe/change your settings at above page >> > >> >> > >> >> > >> _______________________________________________ >> > >> sword-devel mailing list: sword-devel@crosswire.org >> > >> http://www.crosswire.org/mailman/listinfo/sword-devel >> > >> Instructions to unsubscribe/change your settings at above page >> > >> > >> > _______________________________________________ >> > sword-devel mailing list: sword-devel@crosswire.org >> > http://www.crosswire.org/mailman/listinfo/sword-devel >> > Instructions to unsubscribe/change your settings at above page >> > >> >> _______________________________________________ >> sword-devel mailing list: sword-devel@crosswire.org >> http://www.crosswire.org/mailman/listinfo/sword-devel >> Instructions to unsubscribe/change your settings at above page > _______________________________________________ > sword-devel mailing list: sword-devel@crosswire.org > http://www.crosswire.org/mailman/listinfo/sword-devel > Instructions to unsubscribe/change your settings at above page
_______________________________________________ sword-devel mailing list: sword-devel@crosswire.org http://www.crosswire.org/mailman/listinfo/sword-devel Instructions to unsubscribe/change your settings at above page