JDEdwards / Oracle EnterpriseOne - jdeStrncpy and jdeStrncpyTerminate

First of all, both the functions were brought into play due to Unicode. Similarly to former sizeof, they should guarantee that the code is safe when manipulating strings. Unfortunately, it is not always the case.

Based on the documentation jdeStrncpy should be always used with DIM()-1 while jdeStrncpyTerminate with DIM() as the third parameter. Unfortunately, this works well for jdeStrncpyTerminate but not really for jdeStrncpy.

Let's assume the following code:
JCHAR szTest1[2];
JCHAR szTest2[2];
JCHAR szTest3[10];
jdeStrncpy(szTest1, _J("ABCD"), DIM(szTest1)-1);

The variable szTest1 was not reset to zeros with {0} thefore it contains garbage. Also the garbage could have been created by a previous logic if there was any. The size of the variable szTest1 is 2 JCHARS so let's assume it contained "XY" before jdeStrncpy (unterminated 2 JCHARs). The value after the assignment is not "A" terminated with 0x00 as expected but "A" followed by "Y" (the last JCHAR was not modified by the function!!). To make things worse the text is not terminated therefore any subsequent logic will be wrong as well.

Let's continue the code above with the following:

jdeStrncpyTerminate(szTest2, _J("1234"), DIM(szTest2));
jdeStrncpyTerminate(szTest3, szTest1, DIM(szTest3));

The assignment to szTest2 works as expected no matter what garbage was in the variable before, the text is properly terminated and the result is "1" (the size is 2 JCHARS, the last one is used to terminate the string with 0x00).

However the assignment to szTest3, although properly coded, does not do what we expect. The result in szTest3 afterwards could possibly be "AY1". The compiler usually allocates memory for variables in the sequence of the declaration so we can assume (however cannot rely on) that szTest2 directly follows szTest1 in memory. As the string in szTest1 is not terminated, it "continues" into the next variable. Therefore the variable szTest3 is filled with an incorrect value. The cause of the problem is in jdeStrncpy.

Resolution: Either use jdeStrncpyTerminate with DIM() OR use jdeStrncpy with DIM()-1 but always make sure the variable is reset to zeros before the operation.

Replacement: If you wish to replace all jdeStrncpy with jdeStrncpyTerminate in your source code, you may use the following strings in the MS Visual Studio replacement:

Find what: {jdeStrncpy:b*}\({[^,]*},{[:b\n]*[^,]*},{[:b\n]*[^)]*}{\):b*}{-1:b*}{\).*;}
Replace with: jdeStrncpyTerminate(,, /* jdeStrncpy replaced with jdeStrncpyTerminate */
Find options / Use: Regular expressions

BTW, be careful about the usage of DIM.

Back to Content

In case of any questions or suggestions please contact David Macek.