You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-dev@xerces.apache.org by "Guangtai Liang (Updated) (JIRA)" <xe...@xml.apache.org> on 2012/02/13 08:28:59 UTC

[jira] [Updated] (XERCESJ-1552) An incomplete fix for the NPE bugs in RangeToken.java

     [ https://issues.apache.org/jira/browse/XERCESJ-1552?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Guangtai Liang updated XERCESJ-1552:
------------------------------------

    Description: 
The fix revision 928735 was aimed to remove an NPE bug on the "this.ranges " in the method "dumpRanges" of the file "/xerces/java/trunk/src/org/apache/xerces/impl/xpath/regex/RangeToken.java" , but it is incomplete. 
Since the "this.ranges" is a class field and also could be null during the run-time execution, it should also be null-checked before being dereferenced in other methods. 

The buggy code locations the same fix needs to be applied at are as bellows: 

Lines 497 and 505 of the method "match"; 

 boolean match(int ch) {
        if (this.map == null)  this.createMap();
        boolean ret;
        if (this.type == RANGE) {
            if (ch < MAPSIZE)
                return (this.map[ch/32] & (1<<(ch&0x1f))) != 0;
            ret = false;
            for (int i = this.nonMapIndex;  i < this.ranges.length;  i += 2) {
                if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
                    return true;
            }
        } else {
            if (ch < MAPSIZE)
                return (this.map[ch/32] & (1<<(ch&0x1f))) == 0;
            ret = true;
            for (int i = this.nonMapIndex;  i < this.ranges.length;  i += 2) {
                if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
                    return false;
            }
        }
        return ret;
    }

Line 517 of the method "createMap". 

private void createMap() {
        int asize = MAPSIZE/32;                 // 32 is the number of bits in `int'.
        int [] map = new int[asize];
        int nonMapIndex = this.ranges.length;
        for (int i = 0; i < asize; ++i) {
            map[i] = 0;
        }
        for (int i = 0; i < this.ranges.length;  i += 2) {
            int s = this.ranges[i];
            int e = this.ranges[i+1];
            if (s < MAPSIZE) {
                for (int j = s; j <= e && j < MAPSIZE; j++) {
                    map[j/32] |= 1<<(j&0x1f); // s&0x1f : 0-31
                }
            } 
            else {
                nonMapIndex = i;
                break;
            }
            if (e >= MAPSIZE) {
                nonMapIndex = i;
                break;
            }
        }
        this.map = map;
        this.nonMapIndex = nonMapIndex;
        //for (int i = 0;  i < asize;  i ++)  System.err.println("Map: "+Integer.toString(this.map[i], 16));
    }

Lines 557 and 580 of the method "toString": 

public String toString(int options) {
        String ret;
        if (this.type == RANGE) {
            if (this == Token.token_dot)
                ret = ".";
            else if (this == Token.token_0to9)
                ret = "\\d";
            else if (this == Token.token_wordchars)
                ret = "\\w";
            else if (this == Token.token_spaces)
                ret = "\\s";
            else {
                StringBuffer sb = new StringBuffer();
                sb.append('[');
                for (int i = 0;  i < this.ranges.length;  i += 2) {
                    if ((options & RegularExpression.SPECIAL_COMMA) != 0 && i > 0)  sb.append(',');
                    if (this.ranges[i] == this.ranges[i+1]) {
                        sb.append(escapeCharInCharClass(this.ranges[i]));
                    } else {
                        sb.append(escapeCharInCharClass(this.ranges[i]));
                        sb.append((char)'-');
                        sb.append(escapeCharInCharClass(this.ranges[i+1]));
                    }
                }
                sb.append(']');
                ret = sb.toString();
            }
        } else {
            if (this == Token.token_not_0to9)
                ret = "\\D";
            else if (this == Token.token_not_wordchars)
                ret = "\\W";
            else if (this == Token.token_not_spaces)
                ret = "\\S";
            else {
                StringBuffer sb = new StringBuffer();
                sb.append("[^");
                for (int i = 0;  i < this.ranges.length;  i += 2) {
                    if ((options & RegularExpression.SPECIAL_COMMA) != 0 && i > 0)  sb.append(',');
                    if (this.ranges[i] == this.ranges[i+1]) {
                        sb.append(escapeCharInCharClass(this.ranges[i]));
                    } else {
                        sb.append(escapeCharInCharClass(this.ranges[i]));
                        sb.append('-');
                        sb.append(escapeCharInCharClass(this.ranges[i+1]));
                    }
                }
                sb.append(']');
                ret = sb.toString();
            }
        }
        return ret;
   }




  was:
The fix revision 928735 was aimed to remove an NPE bug on the "this.ranges " in the method "dumpRanges" of the file "/xerces/java/trunk/src/org/apache/xerces/impl/xpath/regex/RangeToken.java" , but it is incomplete. 
Since the "this.ranges" is a class field and also could be null during the run-time execution, it should also be null-checked before being dereferenced in other methods. 

The buggy code locations the same fix needs to be applied at are as bellows: 

Lines 497 and 505 of the method "match"; 

 boolean match(int ch) {
        if (this.map == null)  this.createMap();
        boolean ret;
        if (this.type == RANGE) {
            if (ch < MAPSIZE)
                return (this.map[ch/32] & (1<<(ch&0x1f))) != 0;
            ret = false;
            for (int i = this.nonMapIndex;  i < this.ranges.length;  i += 2) {
                if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
                    return true;
            }
        } else {
            if (ch < MAPSIZE)
                return (this.map[ch/32] & (1<<(ch&0x1f))) == 0;
            ret = true;
            for (int i = this.nonMapIndex;  i < this.ranges.length;  i += 2) {
                if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
                    return false;
            }
        }
        return ret;
    }

Line 517 of the method "createMap". 

private void createMap() {
        int asize = MAPSIZE/32;                 // 32 is the number of bits in `int'.
        int [] map = new int[asize];
        int nonMapIndex = this.ranges.length;
        for (int i = 0; i < asize; ++i) {
            map[i] = 0;
        }
        for (int i = 0; i < this.ranges.length;  i += 2) {
            int s = this.ranges[i];
            int e = this.ranges[i+1];
            if (s < MAPSIZE) {
                for (int j = s; j <= e && j < MAPSIZE; j++) {
                    map[j/32] |= 1<<(j&0x1f); // s&0x1f : 0-31
                }
            } 
            else {
                nonMapIndex = i;
                break;
            }
            if (e >= MAPSIZE) {
                nonMapIndex = i;
                break;
            }
        }
        this.map = map;
        this.nonMapIndex = nonMapIndex;
        //for (int i = 0;  i < asize;  i ++)  System.err.println("Map: "+Integer.toString(this.map[i], 16));
    }



    
> An incomplete fix for the NPE bugs in RangeToken.java
> -----------------------------------------------------
>
>                 Key: XERCESJ-1552
>                 URL: https://issues.apache.org/jira/browse/XERCESJ-1552
>             Project: Xerces2-J
>          Issue Type: Bug
>          Components: Other
>            Reporter: Guangtai Liang
>            Priority: Critical
>              Labels: incomplete_fix, missing_fixes
>
> The fix revision 928735 was aimed to remove an NPE bug on the "this.ranges " in the method "dumpRanges" of the file "/xerces/java/trunk/src/org/apache/xerces/impl/xpath/regex/RangeToken.java" , but it is incomplete. 
> Since the "this.ranges" is a class field and also could be null during the run-time execution, it should also be null-checked before being dereferenced in other methods. 
> The buggy code locations the same fix needs to be applied at are as bellows: 
> Lines 497 and 505 of the method "match"; 
>  boolean match(int ch) {
>         if (this.map == null)  this.createMap();
>         boolean ret;
>         if (this.type == RANGE) {
>             if (ch < MAPSIZE)
>                 return (this.map[ch/32] & (1<<(ch&0x1f))) != 0;
>             ret = false;
>             for (int i = this.nonMapIndex;  i < this.ranges.length;  i += 2) {
>                 if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
>                     return true;
>             }
>         } else {
>             if (ch < MAPSIZE)
>                 return (this.map[ch/32] & (1<<(ch&0x1f))) == 0;
>             ret = true;
>             for (int i = this.nonMapIndex;  i < this.ranges.length;  i += 2) {
>                 if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
>                     return false;
>             }
>         }
>         return ret;
>     }
> Line 517 of the method "createMap". 
> private void createMap() {
>         int asize = MAPSIZE/32;                 // 32 is the number of bits in `int'.
>         int [] map = new int[asize];
>         int nonMapIndex = this.ranges.length;
>         for (int i = 0; i < asize; ++i) {
>             map[i] = 0;
>         }
>         for (int i = 0; i < this.ranges.length;  i += 2) {
>             int s = this.ranges[i];
>             int e = this.ranges[i+1];
>             if (s < MAPSIZE) {
>                 for (int j = s; j <= e && j < MAPSIZE; j++) {
>                     map[j/32] |= 1<<(j&0x1f); // s&0x1f : 0-31
>                 }
>             } 
>             else {
>                 nonMapIndex = i;
>                 break;
>             }
>             if (e >= MAPSIZE) {
>                 nonMapIndex = i;
>                 break;
>             }
>         }
>         this.map = map;
>         this.nonMapIndex = nonMapIndex;
>         //for (int i = 0;  i < asize;  i ++)  System.err.println("Map: "+Integer.toString(this.map[i], 16));
>     }
> Lines 557 and 580 of the method "toString": 
> public String toString(int options) {
>         String ret;
>         if (this.type == RANGE) {
>             if (this == Token.token_dot)
>                 ret = ".";
>             else if (this == Token.token_0to9)
>                 ret = "\\d";
>             else if (this == Token.token_wordchars)
>                 ret = "\\w";
>             else if (this == Token.token_spaces)
>                 ret = "\\s";
>             else {
>                 StringBuffer sb = new StringBuffer();
>                 sb.append('[');
>                 for (int i = 0;  i < this.ranges.length;  i += 2) {
>                     if ((options & RegularExpression.SPECIAL_COMMA) != 0 && i > 0)  sb.append(',');
>                     if (this.ranges[i] == this.ranges[i+1]) {
>                         sb.append(escapeCharInCharClass(this.ranges[i]));
>                     } else {
>                         sb.append(escapeCharInCharClass(this.ranges[i]));
>                         sb.append((char)'-');
>                         sb.append(escapeCharInCharClass(this.ranges[i+1]));
>                     }
>                 }
>                 sb.append(']');
>                 ret = sb.toString();
>             }
>         } else {
>             if (this == Token.token_not_0to9)
>                 ret = "\\D";
>             else if (this == Token.token_not_wordchars)
>                 ret = "\\W";
>             else if (this == Token.token_not_spaces)
>                 ret = "\\S";
>             else {
>                 StringBuffer sb = new StringBuffer();
>                 sb.append("[^");
>                 for (int i = 0;  i < this.ranges.length;  i += 2) {
>                     if ((options & RegularExpression.SPECIAL_COMMA) != 0 && i > 0)  sb.append(',');
>                     if (this.ranges[i] == this.ranges[i+1]) {
>                         sb.append(escapeCharInCharClass(this.ranges[i]));
>                     } else {
>                         sb.append(escapeCharInCharClass(this.ranges[i]));
>                         sb.append('-');
>                         sb.append(escapeCharInCharClass(this.ranges[i+1]));
>                     }
>                 }
>                 sb.append(']');
>                 ret = sb.toString();
>             }
>         }
>         return ret;
>    }

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe, e-mail: j-dev-unsubscribe@xerces.apache.org
For additional commands, e-mail: j-dev-help@xerces.apache.org