Hi Anders,
   Currently in ntfimcnd, the SaNameT arrived from IMM has null-terminated
   string,  and  not  much code in ntfimcnd to deal with null or non-null
   terminated string.
   The  problem  is  mostly between NTF and its other users, who send the
   notification/notifying objects and expect exactly the same ones in the
   callback, so as you suggested, it's dealt in ntf agent/library for now
   Another issue that I have to *clone* the string pointer inside long dn
   objects:
   - As sending notification, app allocates notification, use saAisNameLend to
   "package" the long dn object. At the end, app calls saNtfNotificationFree(),
   as result the ntfsv_free_header() will free these long dn objects. At this
   moment, ntfsv_free_header() does not have to worry the string pointer since
   app will free it
   - In case of callback, the ntf agent allocates a new notification and also
   new long dn objects are allocated. At the end of receiving callback, the app
   also calls saNtfNotificationFree() to free the received notification in
   callback, ... ntfsv_free_header() now has to free the string pointer in
   these long dn objects.
   Both  cases  in ntfsv_free_header(), if I can distinguish notification
   generated by app or ntf agent (in callback), I would not have to clone the
   string pointer.
   Thanks,
   Minh
   On 7/7/2014 6:22 PM, Anders Bjornerstedt wrote:

     Anders Bjornerstedt wrote:

     About null terminated or not strings in SaNameT.
     The IMM handles this issue like this (not BEFORE the long DN support).


     That should have been: (note BEFORE the long DN support).
     /AndersBj

     1) The actual max length of DNs supported by the IMM is 255 bytes, not
     256.
     This is to allow all SaNameT values to be null termianted which is a HUGE
     simplification in
     all internal code for trace/log etc.
     2) An SaNameT that arrives over the IMMA API from a user can of course not
     be assumed to be null terminated.
     But all IMMA APIs that do receive an SaNameT from the user will check that
     the length is at most 255 bytes and
     then actually write a terminating null byte into the SaNameT struct.
     3) Only the agent/library code should need to deal with the (quite frankly
     stupid) SaNameT type.
     Server code should not use SaNaameT.
     So I really dont like to see the code in either library or server getting
     ccomplicated just because
     some SaNameT received from a user may not be null terminated. Plug that
     problem at the source
     close to the user API.
     Given that this is done, you should be able to use the lend and borrow
     functions and avoid any
     unnecessary cloning/copying.
     Ntf may have legacy code (messages etc) that use SaNameT in the server.
     Even if you have that and thus use SaNameT more than is really needed, I
     strongly suggest
     you null terminate SaNameTs close to the source (the ntf agent/library
     user), also for NTF.
     /AndesBj
     minhchau wrote:


     Please find comments inline
     Thanks,
     Minh
     On 7/4/2014 9:48 PM, Zoran Milinkovic wrote:


     Hi,
     Find my comments inline started with [Zoran].
     -----Original Message-----
     From: Minh Hon Chau [[1]mailto:minh.c...@dektech.com.au]
     Sent: den 2 juli 2014 07:50
     To:   Anders   Widell;   [2]mathi.naic...@oracle.com;  Hans  Feldt;
     [3]praveen.malv...@oracle.com
     Cc: [4]opensaf-devel@lists.sourceforge.net
     Subject: [devel] [PATCH 2 of 5] NTF: Adapt NTF common library to support
     long DNs [#873]
       osaf/libs/common/ntfsv/Makefile.am         |    1 +
       osaf/libs/common/ntfsv/include/ntfsv_mem.h |    7 +
       osaf/libs/common/ntfsv/ntfsv_enc_dec.c     |   37 ++++--
             osaf/libs/common/ntfsv/ntfsv_mem.c              |       167
     +++++++++++++++++++++++++++-
       4 files changed, 191 insertions(+), 21 deletions(-)
     diff           --git           a/osaf/libs/common/ntfsv/Makefile.am
     b/osaf/libs/common/ntfsv/Makefile.am
     --- a/osaf/libs/common/ntfsv/Makefile.am
     +++ b/osaf/libs/common/ntfsv/Makefile.am
     @@ -23,6 +23,7 @@ SUBDIRS = include
       noinst_LTLIBRARIES = libntfsv_common.la
         libntfsv_common_la_CPPFLAGS = \
     +    -DSA_EXTENDED_NAME_SOURCE \
           $(AM_CPPFLAGS) \
           -I$(top_srcdir)/osaf/libs/common/ntfsv/include
           diff    --git    a/osaf/libs/common/ntfsv/include/ntfsv_mem.h
     b/osaf/libs/common/ntfsv/include/ntfsv_mem.h
     --- a/osaf/libs/common/ntfsv/include/ntfsv_mem.h
     +++ b/osaf/libs/common/ntfsv/include/ntfsv_mem.h
     @@ -97,6 +97,13 @@ extern "C" {
           void
     ntfsv_filter_obj_cr_del_free(SaNtfObjectCreateDeleteNotificationFilterT
     *f);
           void
     ntfsv_filter_attr_ch_free(SaNtfAttributeChangeNotificationFilterT *f);
       +    SaAisErrorT ntfsv_sanamet_copy(SaNameT* pDes, SaNameT* pSrc);
     +    bool ntfsv_sanamet_is_valid(const SaNameT* pName);
     +    void ntfsv_sanamet_clone_strptr(SaNameT* pName);
     +    SaStringT ntfs_sanamet_strdup(SaNameT* pName);
     +    size_t ntfs_sanamet_length(const SaNameT* pName);
     +    void ntfs_sanamet_steal(SaStringT value, size_t length, SaNameT*
     pName);
     +    void ntfs_sanamet_alloc(SaConstStringT value, size_t length, SaNameT*
     pName);
       #ifdef  __cplusplus
       }
       #endif
     diff         --git         a/osaf/libs/common/ntfsv/ntfsv_enc_dec.c
     b/osaf/libs/common/ntfsv/ntfsv_enc_dec.c
     --- a/osaf/libs/common/ntfsv/ntfsv_enc_dec.c
     +++ b/osaf/libs/common/ntfsv/ntfsv_enc_dec.c
     @@ -18,6 +18,8 @@
       #include <ncsencdec_pub.h>
       #include "ntfsv_enc_dec.h"
       #include "ntfsv_mem.h"
     +#include "osaf_extended_name.h"
     +#include "saAis.h"
         typedef union {
           uint32_t uint32_val;
     @@ -334,19 +336,22 @@ static uint32_t decodeSaNtfAttribute(NCS
       static uint32_t encodeSaNameT(NCS_UBAID *uba, uint8_t *p8, SaNameT
     *name)
       {
           uint32_t rv;
     -
           p8 = ncs_enc_reserve_space(uba, 2);
           if (!p8) {
               TRACE("ncs_enc_reserve_space failed");
               return NCSCC_RC_OUT_OF_MEM;
           }
     -    if (name->length > SA_MAX_NAME_LENGTH) {
     -        LOG_ER("SaNameT length too long %hd", name->length);
     -        osafassert(0);
     -    }
     -    ncs_encode_16bit(&p8, name->length);
     -    ncs_enc_claim_space(uba, 2);
     -        rv    =    ncs_encode_n_octets_in_uba(uba,    name->value,
     (uint32_t)name->length);
     +
     +    if (!ntfsv_sanamet_is_valid(name)) {
     +        LOG_ER("SaNameT is invalid");
     +         osafassert(0);
     +     }
     +
     +    SaConstStringT value = osaf_extended_name_borrow(name);
     +    size_t length = ntfs_sanamet_length(name);
     +    ncs_encode_16bit(&p8, length);
     +     ncs_enc_claim_space(uba, 2);
     +    rv = ncs_encode_n_octets_in_uba(uba, (uint8_t*) value, (uint32_t)
     length);
           return rv;
       }
       @@ -355,14 +360,22 @@ static uint32_t decodeSaNameT(NCS_UBAID
           uint8_t local_data[2];
           uint32_t rv;
           p8 = ncs_dec_flatten_space(uba, local_data, 2);
     -    name->length = ncs_decode_16bit(&p8);
     -    if (name->length > SA_MAX_NAME_LENGTH) {
     -        LOG_ER("SaNameT length too long: %hd", name->length);
     +    size_t length = ncs_decode_16bit(&p8);
     +    if (length > kMaxDnLength) {
     +        LOG_ER("SaNameT length too long: %zu", length);
               /* this should not happen */
               osafassert(0);
           }
           ncs_dec_skip_space(uba, 2);
     -       rv    =    ncs_decode_n_octets_from_uba(uba,   name->value,
     (uint32_t)name->length);
     +    char* value = (char*) malloc(length + 1);
     +    if (value == NULL) {
     +        LOG_ER("Out of memory");
     +        /* this should not happen */
     +        osafassert(0);
     +    }
     +    rv = ncs_decode_n_octets_from_uba(uba, (uint8_t*) value, (uint32_t)
     length);
     +    value[length] = '\0';
     +    ntfs_sanamet_steal(value, length, name);
           return rv;
       }
             diff       --git       a/osaf/libs/common/ntfsv/ntfsv_mem.c
     b/osaf/libs/common/ntfsv/ntfsv_mem.c
     --- a/osaf/libs/common/ntfsv/ntfsv_mem.c
     +++ b/osaf/libs/common/ntfsv/ntfsv_mem.c
     @@ -18,6 +18,8 @@
       #include <saNtf.h>
       #include <stdlib.h>
       #include "ntfsv_mem.h"
     +#include "osaf_extended_name.h"
     +#include "saAis.h"
       #include <logtrace.h>
               void   ntfsv_free_header(const   SaNtfNotificationHeaderT
     *notificationHeader)
     @@ -27,10 +29,14 @@ void ntfsv_free_header(const SaNtfNotifi
               free(notificationHeader->eventType);
           if (notificationHeader->eventTime != NULL)
               free(notificationHeader->eventTime);
     -    if (notificationHeader->notificationObject != NULL)
     +    if (notificationHeader->notificationObject != NULL) {
     +        osaf_extended_name_free(notificationHeader->notificationObject);
               free(notificationHeader->notificationObject);
     -    if (notificationHeader->notifyingObject != NULL)
     +    }
     +    if (notificationHeader->notifyingObject != NULL) {
     +        osaf_extended_name_free(notificationHeader->notifyingObject);
               free(notificationHeader->notifyingObject);
     +    }
           if (notificationHeader->notificationClassId != NULL)
               free(notificationHeader->notificationClassId);
           if (notificationHeader->notificationId != NULL)
     @@ -486,10 +492,10 @@ void ntfsv_copy_ntf_header(SaNtfNotifica
           *(dest->eventTime) = *(src->eventTime);
             /* Set Notification Object */
     -    *(dest->notificationObject) = *(src->notificationObject);
     +                      ntfsv_sanamet_copy(dest->notificationObject,
     src->notificationObject);
             /* Set Notifying Object */
     -    *(dest->notifyingObject) = *(src->notifyingObject);
     +    ntfsv_sanamet_copy(dest->notifyingObject, src->notifyingObject);
             /* set Notification Class Identifier */
                       dest->notificationClassId->vendorId             =
     src->notificationClassId->vendorId;
     @@ -954,7 +960,7 @@ SaAisErrorT ntfsv_filter_header_alloc(Sa
           /* Notification objects */
           if (numNotificationObjects != 0) {
            -             header->notificationObjects     =     (SaNameT
     *)malloc(numNotificationObjects * sizeof(SaNameT));
     +               header->notificationObjects        =       (SaNameT
     *)calloc(numNotificationObjects, sizeof(SaNameT));
               if (header->notificationObjects == NULL) {
                   TRACE_1("Out of memory notificationObjects");
                   rc = SA_AIS_ERR_NO_MEMORY;
     @@ -964,7 +970,7 @@ SaAisErrorT ntfsv_filter_header_alloc(Sa
             /* Notifying objects */
           if (numNotifyingObjects != 0) {
     -        header->notifyingObjects = (SaNameT *)malloc(numNotifyingObjects
     * sizeof(SaNameT));
     +        header->notifyingObjects = (SaNameT *)calloc(numNotifyingObjects,
     sizeof(SaNameT));
               if (header->notifyingObjects == NULL) {
                   TRACE_1("Out of memory notifyingObjects");
                   rc = SA_AIS_ERR_NO_MEMORY;
     @@ -1174,10 +1180,18 @@ error_free:
         void ntfsv_filter_header_free(SaNtfNotificationFilterHeaderT *header)
       {
     +    size_t i;
     +
     +    for (i = 0; i < header->numNotificationObjects; ++i)
     +        osaf_extended_name_free(header->notificationObjects + i);
     +
     +    for (i = 0; i < header->numNotifyingObjects; ++i)
     +        osaf_extended_name_free(header->notifyingObjects + i);
     +
           free(header->eventTypes);
     -    free(header->notificationObjects);
     -    free(header->notifyingObjects);
     -    free(header->notificationClassIds);
     +     free(header->notificationObjects);
     +     free(header->notifyingObjects);
     +     free(header->notificationClassIds);
       }
       voidntfsv_filter_sec_alarm_free(SaNtfSecurityAlarmNotificationFilterT
     *s_filter)
     @@ -1226,3 +1240,138 @@ void ntfsv_filter_attr_ch_free(SaNtfAttr
           }
       }
       +/**
     + *  @Brief: Copy SaNameT pointed by pSrc to pDes
     + *
     + */
     +SaAisErrorT ntfsv_sanamet_copy(SaNameT* pDes, SaNameT* pSrc)
     +{
     +    SaAisErrorT rc = SA_AIS_OK;
     +    if (osaf_is_an_extended_name(pDes)) {
     +        TRACE("Can not modify the existing longDn object");
     +        return SA_AIS_ERR_EXIST;
     +    }
     +    if (osaf_is_an_extended_name(pSrc)) {
     +        osaf_extended_name_alloc(osaf_extended_name_borrow(pSrc), pDes);
     +    } else {
     +        /* pSrc is old SaNameT format, @.length could be counted with or
     +         * without null-termination, we need to preserve the @.length,
     +          * just a memcpy here
     +         */
     +         memcpy(pDes, pSrc, sizeof(SaNameT));
     +    }
     +    return rc;
     [Zoran] Minor comment. "rc" is not necessary in the function.
     "return rc;" can be replaced with "return SA_AIS_OK;", and skip using "rc"


     [Minh]: Will remove rc


     +}
     +
     +/**
     + *  @Brief: Check SaNameT is a valid formation
     + *
     + */
     +bool ntfsv_sanamet_is_valid(const SaNameT* pName)
     +{
     +    if (!osaf_is_extended_name_valid(pName)) {
     +        LOG_ER("Environment variable SA_ENABLE_EXTENDED_NAMES "
     +            "is not set, or not using extended name api");
     +        return false;
     +    }
     +    if (osaf_extended_name_length(pName) > kMaxDnLength) {
     +        LOG_ER("Exceeding maximum of extended name length(%u)"
     +            ,kMaxDnLength);
     +        return false;
     +    }
     +    return true;
     +}
     +
     +/**
     + *  @Brief: Clone the string pointer in extended name
     + *
     + */
     +void ntfsv_sanamet_clone_strptr(SaNameT* pName)
     +{
     +    if (osaf_is_an_extended_name(pName))
     +        osaf_extended_name_alloc(osaf_extended_name_borrow(pName),
     pName);
     [Zoran] Please check how this function is used. Seems like that this code
     leads to a memory leak. Pointer in the extended name is overwritten.
     I'll give you an example of using this function in another email.


     [Minh]: I will explain in another email.


     +}
     +
     +/**
     + *  @Brief: Return the length of string specified in SaNameT type.
     + *
     + */
     +size_t ntfs_sanamet_length(const SaNameT* pName)
     +{
     +    if (osaf_is_an_extended_name(pName))
     +        return osaf_extended_name_length(pName);
     +
     +    /* In case of unextended name, the length returned by
     +     * osaf_extended_name_length sometimes is greater than @.length since
     if
     +     * @.value is not a null-terminated string, and it reads over the
     +     * @.length character(s). Here we need the length specified in
     @.length
     +     */
     [Zoran] This text is not true. osaf_extended_name_length() takes care of
     non-null-terminated string.
     If it's not extended name, then osaf_extended_name_length() will return
     max @.length.
     Taken from osaf_extended_name_length the code:
     length = strnlen((const char*) (name->_opaque + 1), length);


     [Minh]: The above text is wrong I agree, and I have sent another email to
     correct it. I should be:
             /* In case of unextended name, sometimes @.length includes the
     count on
              * null-termination, and osaf_extended_name_length returns the
     length
              * excluding the null-termination which less 1 than the @.length.
     Here
              * we need the length specified in @.length. This case mainly
     applies
               * in encodeSaNameT/decodeSaNameT in order to preserve the
     original
              * @.length value
              */
              And that's the reason I need to retrieve 2 first bytes of SaNameT
     rather than returned by osaf_extended_name_length
                  Otherwise    the    ntftest    fails    because    the
     notificationObject/notifyingObject returned in callback having @.length
     less 1 than the expectation.
              And I don't think that's the issue in ntftest, since the length
     in   old  SaNameT  is  not  strictly  required  with/or  without  a
     null-termination.


     +    size_t length = 0;
     +    memcpy(&length, (char*)pName, 2);
     [Zoran] This code will not work correct on big endian system. The size of
     size_t is greater than 16 bits.
     This  is a minor comment, since ntfs_sanamet_length can be replaced
     osaf_extended_name_length.


     [Minh]: will fix


     +    osafassert(length < SA_MAX_UNEXTENDED_NAME_LENGTH);
     +    return length;
     +}
     +
     +/**
     + *  @Brief: Allocate the new null-terminated string in SaNameT type, and
     return
     + *            the pointer of this new string.
     + *
     + */
     +SaStringT ntfs_sanamet_strdup(SaNameT* pName)
     +{
     +    SaStringT pRtr;
     +    SaConstStringT pStr;
     +
     +    size_t length = 0;
     +    if (osaf_is_an_extended_name(pName)) {
     +        pStr = osaf_extended_name_borrow(pName);
     +        length = strlen(pStr) + 1;
     +    } else {
     +        length = ntfs_sanamet_length(pName);
     +        osafassert(length < SA_MAX_UNEXTENDED_NAME_LENGTH);
     +        pStr = (char*)(pName) + 2;
     +        /* for the case of non null-terminated in @.value */
     +        if (pStr[length - 1] != '\0')
     +            length++;
     +
     +    }
     [Zoran] As I mentioned in the comment before, osaf_extended_name_length()
     works fine with both extended and non-extended names.
     There is no need for making double work and making distinguish between
     extended and non-extended name. osaf_extended_name_* functions should take
     care of that.
     The code above can be safely replaced with:
     length = osaf_extended_name_length(pName) + 1;
     pStr = osaf_extended_name_borrow(pName);
     +    pRtr = (char*) malloc(length);
     +    if (pRtr == NULL) {
     +        LOG_ER("out of memory");
     +        return NULL;
     +    }
     +    memcpy(pRtr, pStr, length);
     [Zoran] memcpy(pRtr, pStr, length - 1);


     [Minh]: The ntfs_sanamet_strdup above is not neat since I use my own
     ntfs_sanamet_length, and It can be simply replaced by your code, but I
     hope   it  would  be  made  as  osaf_extended_name_strdup,  because
     osaf_extended_name_borrow does not guarantee a null-terminated string.
     Everytime we want to compare 2 SaNameT, we have to get length and put a
     NULL at the correct position in borrowed string.


     Best regards,
     Zoran
     +    pRtr[length - 1] = '\0';
     +    return pRtr;
     +}
     +
     +/**
     + *  @Brief: Create SaNameT input by string @value and @length,
     + *            @value is not freed then
     + */
     +void ntfs_sanamet_alloc(SaConstStringT value, size_t length, SaNameT*
     pName)
     +{
     +    osaf_extended_name_alloc(value, pName);
     +     /*  Accept the old SaNameT which's @.length counting the null
     termination */
     +    if (!osaf_is_an_extended_name(pName)
     +        && ((ntfs_sanamet_length(pName)+1) == length)) {
     +        memcpy(pName, &length, 2);
     +    }
     +}
     +
     +/**
     + *  @Brief: Create SaNameT input by string @value and @length,
     + *            @value is freed then
     + */
     +void ntfs_sanamet_steal(SaStringT value, size_t length, SaNameT* pName)
     +{
     +    /* create pName by string @value */
     +    osaf_extended_name_free(pName);
     +    osaf_extended_name_steal(value, pName);
     +
     +     /*  Accept the old SaNameT which's @.length counting the null
     termination */
     +    if (!osaf_is_an_extended_name(pName)
     +        && ((ntfs_sanamet_length(pName)+1) == length)) {
     +        memcpy(pName, &length, 2);
     +    }
     +}
     --------------------------------------------------------------------------
     ----
     Open source business process management suite built on Java and Eclipse
     Turn processes into business applications with Bonita BPM Community
     Edition
     Quickly connect people, data, and systems into organized workflows
     Winner of BOSSIE, CODIE, OW2 and Gartner awards
     [5]http://p.sf.net/sfu/Bonitasoft
     _______________________________________________
     Opensaf-devel mailing list
     [6]Opensaf-devel@lists.sourceforge.net
     [7]https://lists.sourceforge.net/lists/listinfo/opensaf-devel


     --------------------------------------------------------------------------
     ----
     Open source business process management suite built on Java and Eclipse
     Turn processes into business applications with Bonita BPM Community
     Edition
     Quickly connect people, data, and systems into organized workflows
     Winner of BOSSIE, CODIE, OW2 and Gartner awards
     [8]http://p.sf.net/sfu/Bonitasoft
     _______________________________________________
     Opensaf-devel mailing list
     [9]Opensaf-devel@lists.sourceforge.net
     [10]https://lists.sourceforge.net/lists/listinfo/opensaf-devel


     --------------------------------------------------------------------------
     ----
     Open source business process management suite built on Java and Eclipse
     Turn processes into business applications with Bonita BPM Community
     Edition
     Quickly connect people, data, and systems into organized workflows
     Winner of BOSSIE, CODIE, OW2 and Gartner awards
     [11]http://p.sf.net/sfu/Bonitasoft
     _______________________________________________
     Opensaf-devel mailing list
     [12]Opensaf-devel@lists.sourceforge.net
     [13]https://lists.sourceforge.net/lists/listinfo/opensaf-devel

References

   1. mailto:minh.c...@dektech.com.au
   2. mailto:mathi.naic...@oracle.com
   3. mailto:praveen.malv...@oracle.com
   4. mailto:opensaf-devel@lists.sourceforge.net
   5. http://p.sf.net/sfu/Bonitasoft
   6. mailto:Opensaf-devel@lists.sourceforge.net
   7. https://lists.sourceforge.net/lists/listinfo/opensaf-devel
   8. http://p.sf.net/sfu/Bonitasoft
   9. mailto:Opensaf-devel@lists.sourceforge.net
  10. https://lists.sourceforge.net/lists/listinfo/opensaf-devel
  11. http://p.sf.net/sfu/Bonitasoft
  12. mailto:Opensaf-devel@lists.sourceforge.net
  13. https://lists.sourceforge.net/lists/listinfo/opensaf-devel
------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to