Ugyanis, ha nem hívódott, akkor az Ora nyilván "csak-be" értelemben használta azt a változót, tehát a 'bind_post_exec'-nek semmit sem kell csinálni vele.
Namost ezt nem merem ("túl nagy módosítás" -- bár nem tudom, miért aggódom, hiszen így sem érdekelt senkit a bug-report), tehát a tákolás-bákolás folyamán a 'dummy_len' a következő pályát fogja befutni:
bind_by_name: belerakjuk a maximum értéket vagy ha az nincs, a string hosszát, vagy valamilyen jó nagy számot (itt nem változtattam semmit)
bind_in_callback: maximum-értékként használjuk (ha az aktuális érték ennél hosszabb, azt levágjuk), azután beállítjuk az aktuális hosszra -- ez utóbbi az új fejlesztés
bind_out_callback: átadjuk 'dummy_len' címét az Orának, hogy ebbe tegye a visszajövő érték hosszát -- ez is új, eddig a zend-string-változó hosszmezőjének címe ment, itt volt típusinkompatibilitás 'size_t' és 'ub4' között (BigEndian 64 patform!)
bind_post_exec: 'dummy_len'-ből vesszük a string hosszát
Említsük meg, hogy a bind_in_callback mindig meghívódik, a bind_out_callback meg csak a kimenő változókra, tehát a csodás tákolásnak mindkét esetben jól kell működnie. (Megjegyzés: látszólag háromféle bind-változó-használat van: IN, OUT és IN OUT, de a valóságban az 'OUT' is 'IN OUT', ezért tanácsos a kimenő változókat NULL-ra állítani hívás előtt.)
20160902.1315
Na ennyit mára a tudomány és a technika újdonságaiból.
https://bugs.php.net/bug.php?id=73002
20160902.1200
Itt is vélek látni valami zavart:
(gdb) p *alenpp
$12 = (ub4 *) 0x70000000009e010
(gdb) p *bufpp
$13 = (void *) 0x70000000009e018
(gdb) ptype val->value.str[0]
type = struct _zend_string {
70000000009e000 zend_refcounted_h gc;
70000000009e008 zend_ulong h;
70000000009e010 size_t len; /* ez itten 64-bites, big endian */
70000000009e018 char val[1];
}
20160902.1115
Ilyen a zend_string:
struct _zend_string {
zend_refcounted_h gc;
zend_ulong h; /* hash value */
size_t len;
char val[1];
};
Ilyen a zend_string_init:
static zend_always_inline zend_string *zend_string_init(const char *str, size_t len, int persistent)
{
zend_string *ret = zend_string_alloc(len, persistent);
memcpy(ZSTR_VAL(ret), str, len);
ZSTR_VAL(ret)[len] = '\0';
return ret;
}
és a zend_string_alloc:
static zend_always_inline zend_string *zend_string_alloc(size_t len, int persistent)
{
zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
GC_REFCOUNT(ret) = 1;
#if 1
/* optimized single assignment */
GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8);
#else
GC_TYPE(ret) = IS_STRING;
GC_FLAGS(ret) = (persistent ? IS_STR_PERSISTENT : 0);
GC_INFO(ret) = 0;
#endif
zend_string_forget_hash_val(ret);
ZSTR_LEN(ret) = len;
return ret;
}
20160902.1040
Szóval van egy ilyen, hogy
ZVAL_STRINGL(val, p, PHP_OCI_PIECE_SIZE);
ennek a végén *(val->value.str) kellene legyen az újonnan foglalt buffer. Ehhez képest val->value.str->val==NULL
Ez lenne a makrókifejtés eredménye:
ZVAL_NEW_STR(val, zend_string_init(p, PHP_OCI_PIECE_SIZE, 0));
ennek a kifejtése:
{
zval *__z = (val);
zend_string *__s = (zend_string_init(p, PHP_OCI_PIECE_SIZE, 0));
Z_STR_P(__z) = __s;
Z_TYPE_INFO_P(__z) = IS_STRING_EX;
}
Talán a zend_string_init ad vissza NULL-pointert?
20160902.0940
Következik a OCIBindDynamic, különös tekintettel a 'php_oci_bind_out_callback' nevű függvényre.
20160902.0935
Most úgy tűnik, hogy az OCIBindByName hatodik paramétere (valuep) egységesen nulla. Nyomozást folytatni.
20160902.0850
Tehát most itt tartunk:
#if PHP_MAJOR_VERSION > 6
#define my_RETURN_STRINGL_DUPLICATE(s,l) RETURN_STRINGL((s),(l))
typedef size_t TStrParamLen;
#else
#define my_RETURN_STRINGL_DUPLICATE(s,l) RETURN_STRINGL((s),(l),1)
typedef int TStrParamLen;
typedef long zend_long;
#endif
20160902.0840
Közben arra vélek gondolni, hogy a 'zend_long' típus az olyan jópofa LLP64-es rendszerek miatt van, amilyen a Windows64... van is ott egy vizsgálat:
#if defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || \
defined(_WIN64)
# define ZEND_ENABLE_ZVAL_LONG64 1
#endif
(Mondjuk az 'intptr_t'-t is használnánk ilyesmire, de a 'zend_long' szebben cseng)
20160902.0755
linuxon megy ugyanez php7-ben. Nem azonos Oracle-verzió ugyan (11 vs 12).
20160902.0725
Itt egy kódrészlet, ami eltérően működik php5-ben és php7-ben:
$sql= 'BEGIN SELECT ename INTO :ename FROM emp WHERE empno=:empno; END;';
$stmt= oci_parse ($conn, $sql);
if ($conn===FALSE) {
$e= oci_error ($conn);
$errstr= $e['message'];
goto RETURN_;
}
$rc= @oci_bind_by_name ($stmt, ":empno", $empno);
if (!$rc) {
$e = oci_error ($stmt);
$errstr= $e['message'];
goto RETURN_;
}
$rc= @oci_bind_by_name ($stmt, ":ename", $ename, 64, SQLT_CHR);
if (!$rc) {
$e = oci_error ($stmt);
$errstr= $e['message'];
goto RETURN_;
}
$rc= oci_execute ($stmt);
if (!$rc) {
$e = oci_error ($stmt);
$errstr= $e['message'];
goto RETURN_;
}
Ez a hibaüzenet php7-ben:
oci_execute(): ORA-03131: an invalid buffer was provided for the next piece
A $ename üres stringként volt inicializálva az oci_bind előtt. Akkor most mi legyen?
20160902.0705
Rendkívül frappánsan menet közben váltunk irányt, ezentúl az elején lesz a bővülés.
Szóval az oci8 nem annyira megy, mint amennyire nem. Persze egy sima SELECT megy, de most egy tárolt eljárást hívnék, és -3113 jön az oci_execute-nál. Természetesen másik gépen ugyanez megy (php5-tel)
Session ID: 336 Serial number: 49540 in /home/projects/szir/include/io_jog.inc on line 72
loc_jog_login (PROBA) returned Oracle execute error:
ORA-03113: end-of-file on communication channel
Úgy látszik, a php-5.6.x sorozat már nem hoz új kihívásokat, adjunk egy egy esélyt a 7.0.10-nek. Van pl. egy ilyen rész a configure során:
sed: Function s/'CPPFLAGS=-D__UNIX__ <nyissz> -DHAVE_OCI_PING'// cannot be parsed.
Ugyanis a CPPFLAGS-ban /perjelek is vannak, pl: -I/usr/local/include -- erre mondaná Váncsa István, hogy 'némely emberi agy egészen másképp működik, mint ahogy azt józan ésszel elvárnánk'
A configure-ban pedig van egy ilyen:
clean_configure_args=$(echo $clean_configure_args | sed -e "s/'$var=$val'//")
Szóval meg akarja tisztítani a paramétereit. Vajon az előző verzióban is előadták ezt? Szerk: Nem, ez új eredmény.
https://bugs.php.net/bug.php?id=72987
Viszont van olyan is, ami nem változik:
https://bugs.php.net/bug.php?id=51558
Aztán van egy pont, ahol kellene neki a ext/pdo_sqlite/libsqlite/sqlite3.c
Ilyen persze nincs. Olyan van, hogy ext/sqlite3/libsqlite/sqlite3.c
"Ezt most így hogy?" Senkinek se hiányzott? Vagy linuxon másképp gányolódik?
Megpróbálkoztatunk egy ilyet:
s;ext/pdo_sqlite/libsqlite/sqlite3;ext/sqlite3/libsqlite/sqlite3;g
20160901.1345: Jó hír, nemcsak az imagick, hanem a házi bővítmény sem fordul az új verzióval:
GlobusPni.c: In function 'zif_glb_set':
GlobusPni.c:168:32: error: 'IS_BOOL' undeclared (first use in this function)
} else if (Z_TYPE_P (optval)==IS_BOOL ||
^
GlobusPni.c:168:32: note: each undeclared identifier is reported only once for each function it appears in
GlobusPni.c: In function 'zif_glb_get':
GlobusPni.c:199:35: error: macro "RETURN_STRINGL" passed 3 arguments, but takes just 2
RETURN_STRINGL (retstr, retlen, 1);
https://wiki.php.net/phpng-upgrading
Kezdem úgy érezni magam, mint a gonosz Lord Helmet az Űrgolyhókban. "Sejtettem, Balfaszokkal vagyok körülvéve"
Persze megpróbálhatok elágazni a ZEND_VERSION alapján:
5.6.x: #define ZEND_VERSION "2.6.0"
7.0.x: #define ZEND_VERSION "3.0.0"
Mielőtt még fellelkesülnénk: #if-ben nem lehet stringösszehasonlítás
Akkor újabb információig válasszuk ezt:
5.6.x: #define PHP_MAJOR_VERSION 5
7.0.x: #define PHP_MAJOR_VERSION 7
Vagyis:
/* 20160901.NT
Nem is lenne az igazi, ha nem tennének bele inkompatibilis változtatást
*/
#if PHP_MAJOR_VERSION > 6
#define my_RETURN_STRINGL_DUPLICATE(s,l) RETURN_STRINGL((s),(l))
#else
#define my_RETURN_STRINGL_DUPLICATE(s,l) RETURN_STRINGL((s),(l),1)
#endif
És akkor jött a Tenkes Kapitánya... Akarom mondani, az újabb hibaüzenet:
ld: 0711-317 ERROR: Undefined symbol: .__zend_malloc
Szerk: hiszti off, csak az import-fájlt kellett bővíteni
20160901.1620: Most tudtam meg, hogy van nekem egy zend_long típusom.
Kicsit meg is ijesztettem magam, mert nem gondoltam rá, hogy a cpp-nek is át kell passzolni a '-maix32 / -maix64' opciók valamelyikét, hogy ugyanazt lássam, mint a valós fordításnál.
20160901.1630:
zend_API.c: zend_parse_parameters -> zend_parse_va_args -> zend_parse_arg -> zend_parse_arg_impl -> zend_parse_arg_string
case 's':
{
char **p = va_arg(*va, char **);
size_t *pl = va_arg(*va, size_t *);
if (!zend_parse_arg_string(arg, p, pl, check_null)) {
return "string";
}
}
break;
Ugyanez 5.6.25-ben:
case 's':
{
char **p = va_arg(*va, char **);
int *pl = va_arg(*va, int *);
Ugye nem kell magyaráznom, hogy ilyen körülmények között mi jött vissza az 'int' típusú 'length_of_strparam' mezőmben? (big endian PowerPC)
- NevemTeve blogja
- A hozzászóláshoz be kell jelentkezni
- 821 megtekintés
Hozzászólások
sed: Function s/'CPPFLAGS=-D__UNIX__ -DHAVE_OCI_PING'// cannot be parsed.
Jajj, ezzel én is jártam így egy saját szkriptben, kellett némi idő, míg rájöttem a hiba okára (mentségemre szóljon, hogy a kifejezés környezeti változóban volt, és nem mindig volt benne per-jel).
- A hozzászóláshoz be kell jelentkezni