ber_len_t tlen = strlen(dv->type);
 
                                for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
-                                       len += STRLENOF("<=>;") + tlen + dv->vals[ j ].bv_len;
+                                       len += STRLENOF("<:=>;") + tlen + 4*((dv->vals[ j ].bv_len - 1)/3 + 1);
                                }
                        }
                }
-               len += dr->derefVal.bv_len;
+               len += dr->derefVal.bv_len + STRLENOF("\n");
                buf = ldap_memalloc( len + 1 );
                if ( buf == NULL ) {
                        rc = LDAP_NO_MEMORY;
                        if ( dv->vals != NULL ) {
                                int j;
                                for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
+                                       int k;
+
+                                       for ( k = 0; k < dv->vals[ j ].bv_len; k++ ) {
+                                               if ( !isprint( dv->vals[ j ].bv_val[k] ) ) {
+                                                       k = -1;
+                                                       break;
+                                               }
+                                       }
+
                                        *ptr++ = '<';
                                        ptr = lutil_strcopy( ptr, dv->type );
+                                       if ( k == -1 ) {
+                                               *ptr++ = ':';
+                                       }
                                        *ptr++ = '=';
-                                       ptr = lutil_strncopy( ptr, dv->vals[ j ].bv_val, dv->vals[ j ].bv_len );
+                                       if ( k == -1 ) {
+                                               k = lutil_b64_ntop( dv->vals[ j ].bv_val, dv->vals[ j ].bv_len, ptr, buf + len - ptr );
+                                               assert( k >= 0 );
+                                               ptr += k;
+                                               
+                                       } else {
+                                               ptr = lutil_memcopy( ptr, dv->vals[ j ].bv_val, dv->vals[ j ].bv_len );
+                                       }
                                        *ptr++ = '>';
                                        *ptr++ = ';';
                                }
                        }
                }
                ptr = lutil_strncopy( ptr, dr->derefVal.bv_val, dr->derefVal.bv_len );
+               *ptr++ = '\n';
                *ptr++ = '\0';
+               assert( ptr <= buf + len );
 
-               tool_write_ldif( LDIF_PUT_COMMENT, NULL, buf, len );
+               tool_write_ldif( LDIF_PUT_COMMENT, NULL, buf, ptr - buf);
 
                ldap_memfree( buf );
        }
 
                         */
 
                        specs = ldap_str2charray( cvalue, ";" );
+                       if ( specs == NULL ) {
+                               fprintf( stderr, _("deref specs \"%s\" invalid\n"),
+                                       cvalue );
+                               exit( EXIT_FAILURE );
+                       }
                        for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ )
                                /* count'em */
 
                        ds = ldap_memcalloc( ispecs + 1, sizeof( LDAPDerefSpec ) );
                        if ( ds == NULL ) {
-                               /* error */
+                               perror( "malloc" );
+                               exit( EXIT_FAILURE );
                        }
 
                        for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) {
 
                                ptr = strchr( specs[ ispecs ], ':' );
                                if ( ptr == NULL ) {
-                                       /* error */
+                                       fprintf( stderr, _("deref specs \"%s\" invalid\n"),
+                                               cvalue );
+                                       exit( EXIT_FAILURE );
                                }
 
                                ds[ ispecs ].derefAttr = specs[ ispecs ];
                }
 
 #ifdef LDAP_CONTROL_X_DEREF
-               if ( ds ) {
+               if ( derefcrit ) {
                        if ( derefval.bv_val == NULL ) {
                                int i;
+
+                               assert( ds != NULL );
+
                                if ( ldap_create_deref_control_value( ld, ds, &derefval ) != LDAP_SUCCESS ) {
                                        return EXIT_FAILURE;
                                }
                                        ldap_charray_free( ds[ i ].attributes );
                                }
                                ldap_memfree( ds );
+                               ds = NULL;
                        }
 
                        if ( ctrl_add() ) {
        if ( sss_keys != NULL ) {
                ldap_free_sort_keylist( sss_keys );
        }
+       if ( derefval.bv_val != NULL ) {
+               ldap_memfree( derefval.bv_val );
+       }
 
        if ( c ) {
                for ( ; save_nctrls-- > 0; ) {
 
 LDAP_LUTIL_F( char* )
 lutil_strncopy LDAP_P(( char *dst, const char *src, size_t n ));
 
+LDAP_LUTIL_F( char* )
+lutil_memcopy LDAP_P(( char *dst, const char *src, size_t n ));
+
 struct tm;
 
 /* use this macro to statically allocate buffer for lutil_gentime */
 
        return a-1;
 }
 
+/* memcopy is like memcpy except it returns a pointer to the byte past
+ * the end of the result buffer, set to NULL. This allows fast construction
+ * of catenated buffers.  Provided for API consistency with lutil_str*copy().
+ */
+char *
+lutil_memcopy(
+       char *a,
+       const char *b,
+       size_t n
+)
+{
+       AC_MEMCPY(a, b, n);
+       return a + n;
+}
+
 #ifndef HAVE_MKSTEMP
 int mkstemp( char * template )
 {
 
                ctrl->ldctl_oid = LDAP_CONTROL_X_DEREF;
                ctrl->ldctl_iscritical = 0;
                ctrl->ldctl_value.bv_len = ctrlval.bv_len;
-               lutil_strncopy( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
+               AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
                ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';
 
                ber_free_buf( ber );