JDK-4892070 : java gets hung in com.sun.jndi.ldap.LdapName$TypeAndValue.unescapeValue()
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.naming
  • Affected Version: 1.3.1_01,1.4.2_06
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: generic,x86
  • Submitted: 2003-07-17
  • Updated: 2003-09-26
  • Resolved: 2003-09-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Duplicate :  
Relates :  
Description
Java 1.3.1_08 process gets hung in
com.sun.jndi.ldap.LdapName$TypeAndValue.unescapeValue(LdapName.java:833),
when "\" escape sequences are used.
Processor load is up to 100%.

The problem is supposed to be nearly strictly reproducible.


1. Testcase
-----------
 Please note, the testcase requires an iPlanet Directory Server Installation
 in order to supply LDAP user info. 
 Customer used iPlanet DS 5.1 SP 1 20020606 (Build 2002.161.2231)
 (Administration Server 5.1 (Build 2002.158.2342)), running on Win2k Advanced
  SP3).

 The testcase consist of the following files:

-rw-r--r--   1 tl15687  sun         3131 Jul 17 13:08 SearchTest.java
-rw-r--r--   1 tl15687  sun          947 Jul 17 13:09 u0146220.ldif


% more SearchTest.java
/*
 * Created on 16.07.2003
 */
 
//package com.sap.security.test;

import java.util.Hashtable;

import javax.naming.*;
import javax.naming.directory.*;
/**
 * @author D037363
 */
public class SearchTest {

  static int timelimit = 50000;
  static int sizelimit = 2000;
  static String baseDN= "cn=test\\u0146220"; 
  static String user = "cn=Directory Manager";
    //please adjust to your settings
  static String password = "<your password>";
  static String providerURL = 
     "ldap://<your directory server>:389/ou=usermapping,ou=portal_ldap,dc=um.wdf.sap.corp";

  public static void main(String[] args) {

    InitialDirContext ctx = openContext();

    SearchControls searchControls = new SearchControls();
    searchControls.setTimeLimit(timelimit);
    searchControls.setCountLimit(sizelimit);
    searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    searchControls.setReturningObjFlag(true);
    searchControls.setDerefLinkFlag(false);

    //searchControls.setReturningAttributes(new String[] {"wpproperty"});

    try {

      //NamingEnumeration answers = ctx.search(baseDN,"(&(objectclass=WPNamespace))", searchControls);
      NamingEnumeration answers = 
         ctx.search(baseDN,"(&(objectclass=applicationmap))", 
                    searchControls);

      // set data bag

      while(answers.hasMore()) {
       // get the entry from the search

       /** this is the statement where the thread never returns !!! */
        SearchResult sr = (SearchResult) answers.next();

        Attributes attrs = sr.getAttributes();
        // if there is no mapping read the attributes by physical name

        NamingEnumeration ae = attrs.getAll();
        while (ae.hasMore()) {
          Attribute oneAttribute = (Attribute)ae.next();
          // get attribute name
          String currentAttribute = oneAttribute.getID();
          if (oneAttribute != null) {
            NamingEnumeration allValues = oneAttribute.getAll();
            while (allValues.hasMore()) {
              System.out.println(  
                currentAttribute+" = "+(String) allValues.next());
            }
          }
        }//end while
      }
    }catch (NoInitialContextException e) {
       String logMessage = 
          "ADAPTER: Test JNDI NoInitialContext Exception when "
           +"reading subcontext. System Msg: " + e;
       System.out.println(logMessage);
  
    }catch(CommunicationException e) {
       String logMessage = 
          "ADAPTER: Test JNDI Communication Exception when reading "
          +"subcontext. System Msg: " + e;
       System.out.println(logMessage);

    }catch (NamingException e) {
       System.out.println(
          "Adapter: Test JNDI Exception getting attributes, DN:"
           +baseDN+" System Msg: ");
    }
  }

  public static InitialDirContext openContext () {
    Hashtable env = new Hashtable();
        
    env.put(Context.INITIAL_CONTEXT_FACTORY,
            "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, user);
    env.put(Context.SECURITY_CREDENTIALS, password);
    env.put(Context.PROVIDER_URL, providerURL);
    InitialDirContext ctx = null;
    try {
      ctx = new InitialDirContext(env);
    } catch (Exception e) {
      System.out.println("exception when trying to open connection "
                         +e.getMessage());
    }

    return ctx;
  }
}

% 

% more u0146220.ldif
dn: uid=de-dus-mgh-m-02\u0146220, ou=People, dc=prod, dc=magis.mgi.de
uid: de-dus-mgh-m-02\u0146220
uid: de-dus-mgh-m-02u0146220
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
givenName: Dirk
sn: Winkler
cn: Dirk Winkler

dn: cn=de-dus-mgh-m-02\u0146220, ou=UserMapping, dc=prod, dc=magis.mgi.de
uid: UGM_de-dus-mgh-m-02\u0146220
objectClass: usergroupmap
objectClass: top
cn: de-dus-mgh-m-02\u0146220
cn: de-dus-mgh-m-02u0146220

dn: cn=de-dus-mgh-m-02\u0146220, ou=customattributes, dc=prod, dc=magis.mgi.d
 e
objectClass: wpuser
objectClass: top
cn: de-dus-mgh-m-02\u0146220
cn: de-dus-mgh-m-02u0146220

dn: cn=com.sapportals.portal.security.usermanagement, cn=de-dus-mgh-m-02\u014
 6220, ou=customattributes, dc=prod, dc=magis.mgi.de
objectClass: wpnamespace
objectClass: top
wpproperty: accessibilitylevel:0
cn: com.sapportals.portal.security.usermanagement

%



2. Thread Dump
--------------

 Java Thread dump shows the following characteristic threads:
 (This information was taken from a process running in SAP Portal environment.)


"Client_Thread_31" prio=5 tid=0x44c84cd8 nid=0x840 waiting for monitor entry [0x
4731f000..0x4731fdbc]
        at java.lang.String.<init>(String.java:364)
        at java.lang.String.<init>(String.java:406)
        at java.lang.String.<init>(String.java:427)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.unescapeValue(LdapName.java:8
33)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.getValueComparable(LdapName.j
ava:714)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.compareTo(LdapName.java:676)
        at com.sun.jndi.ldap.LdapName$Rdn.compareTo(LdapName.java:616)
        at com.sun.jndi.ldap.LdapName$Rdn.equals(LdapName.java:605)
        at com.sun.jndi.ldap.LdapName.matches(LdapName.java:245)
        at com.sun.jndi.ldap.LdapName.startsWith(LdapName.java:195)
[...]
"Client_Thread_30" prio=5 tid=0x44c83e80 nid=0x6c4 waiting for monitor entry [0x
472df000..0x472dfdbc]
        at java.lang.String.<init>(String.java:364)
        at java.lang.String.<init>(String.java:406)
        at java.lang.String.<init>(String.java:427)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.unescapeValue(LdapName.java:8
33)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.getValueComparable(LdapName.j
ava:714)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.compareTo(LdapName.java:676)
        at com.sun.jndi.ldap.LdapName$Rdn.compareTo(LdapName.java:616)
        at com.sun.jndi.ldap.LdapName$Rdn.equals(LdapName.java:605)
        at com.sun.jndi.ldap.LdapName.matches(LdapName.java:245)
        at com.sun.jndi.ldap.LdapName.startsWith(LdapName.java:195)
        at com.sun.jndi.ldap.LdapSearchEnumeration.createItem(LdapSearchEnumerat
ion.java:52)
[...]
"Client_Thread_28" prio=5 tid=0x44c82920 nid=0x8e4 waiting for monitor entry [0x
4725e000..0x4725fdbc]
        at sun.io.ByteToCharUTF8.convert(ByteToCharUTF8.java:45)
        at java.lang.String.<init>(String.java:367)
        at java.lang.String.<init>(String.java:406)
        at java.lang.String.<init>(String.java:427)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.unescapeValue(LdapName.java:8
33)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.getValueComparable(LdapName.j
ava:714)
        at com.sun.jndi.ldap.LdapName$TypeAndValue.compareTo(LdapName.java:676)
        at com.sun.jndi.ldap.LdapName$Rdn.compareTo(LdapName.java:616)
        at com.sun.jndi.ldap.LdapName$Rdn.equals(LdapName.java:605)
        at com.sun.jndi.ldap.LdapName.matches(LdapName.java:245)
        at com.sun.jndi.ldap.LdapName.startsWith(LdapName.java:195)
[...]

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b22
02-09-2004

EVALUATION ###@###.### 2003-07-17 There are two issues here. First, SearchTest begins with: static String baseDN= "cn=test\\u0146220"; where baseDN is used an a JNDI composite name that gets mapped without modification to an LDAP DN. This is not doing what was probably intended. The double-backslash prevents \u0146 from being interpreted as a a Unicode escape. Instead, the DN winds up literally containing the characters: t e s t \ u 0 1 4 6 2 2 0. Those characters do not form a valid DN according to RFC 2253. Dropping one of the backslashes from the baseDN literal will do what appears to have been intended: static String baseDN= "cn=test\u0146220"; This DN contains the desired Unicode character, which the JNDI code should convert to the proper UTF-8 encoding. The second issue is that, when given this incorrect value, the LDAP name parser hangs. This is indeed a bug, though probably a low priority one. The analysis in the Comments section of the bug report is correct. One possible fix would be for unescapeValue() or maybe getUtf8Octets() to complain when getUtf8Octets() doesn't find any escaped octets. ###@###.### 2003-07-18 Thank you very much for this immediate evaluation. The customer indeed got the requirement to compute literal "\" characters. You probably were misguided by the character "u", immediately following the "\" character. The UTF-8 strings that customer needs to process have the following syntax: <domainname><single-backslash><user-identification> So, there is a single, literal backslash in the middle as the separation character. This syntax cannot be changed as it comes from Microsoft MS ADS primary authentication server. According to RFC1522 a single "\" is not allowed in a DN and must be escaped. As far Java code, there are two more levels of escaping needed: http://java.sun.com/products/jndi/tutorial/beyond/names/syntax.html Finally, Java Code will need to be written like this: String baseDN = "uid=de-dus-mgh-m-02\\\\\\\\u0146220" Special thanks to Jaya Hangal <###@###.###> for pointing this out. Would you like me to file a separate bug for the parser problem ? ---------------- ###@###.### 2003-07-19 ###@###.### - Sun EMEA Technical Support Group wrote: > We can track the parser bug with the same bug ID. > We are working on this code base for tiger (J2SE1.5) and we will fix > it in that release. All right. Then I will add a much more simple testcase for this: % cat JndiTest.java import com.sun.jndi.ldap.*; public class JndiTest { public static void main(String[] args) { System.out.println(LdapName.unescapeAttributeValue("ab\\uv")); } } > I believe this is not a show stopper for the customer as they can > solve this problem by using the backslashes properly - the right way. You are right. The parser bug was found accidentally and should not be customer's main concern. With the note above, I am lowering the priority of this bug to P3 and committing it for tiger. ------------------
02-09-2004

PUBLIC COMMENTS Java 1.3.1_08 process gets hung in com.sun.jndi.ldap.LdapName$TypeAndValue.unescapeValue(LdapName.java:833), when "\" escape sequences are used.
02-09-2004