diff --git a/hphp/idl/bzip2.idl.json b/hphp/idl/bzip2.idl.json index c09bfe45f..260b14c1e 100644 --- a/hphp/idl/bzip2.idl.json +++ b/hphp/idl/bzip2.idl.json @@ -34,7 +34,7 @@ "args": [ { "name": "filename", - "type": "String", + "type": "Variant", "desc": "The name of the file to open." }, { @@ -226,4 +226,4 @@ ], "classes": [ ] -} \ No newline at end of file +} diff --git a/hphp/runtime/base/file/bzip2_file.cpp b/hphp/runtime/base/file/bzip2_file.cpp index b96973381..5f6b0c31f 100644 --- a/hphp/runtime/base/file/bzip2_file.cpp +++ b/hphp/runtime/base/file/bzip2_file.cpp @@ -30,6 +30,10 @@ BZ2File::BZ2File(): m_bzFile(nullptr), m_eof(false) { m_innerFile->unregister(); } +BZ2File::BZ2File(PlainFile* innerFile): m_bzFile(nullptr), m_eof(false) { + m_innerFile = innerFile; +} + BZ2File::~BZ2File() { if (m_bzFile) closeImpl(); diff --git a/hphp/runtime/base/file/bzip2_file.h b/hphp/runtime/base/file/bzip2_file.h index b41b7505c..613aa5934 100644 --- a/hphp/runtime/base/file/bzip2_file.h +++ b/hphp/runtime/base/file/bzip2_file.h @@ -35,6 +35,7 @@ public: CStrRef o_getClassNameHook() const { return s_class_name; } BZ2File(); + BZ2File(PlainFile* innerFile); virtual ~BZ2File(); bool open(CStrRef filename, CStrRef mode); diff --git a/hphp/runtime/base/file/file.h b/hphp/runtime/base/file/file.h index 7435ddaf3..945e58bd0 100644 --- a/hphp/runtime/base/file/file.h +++ b/hphp/runtime/base/file/file.h @@ -121,6 +121,8 @@ public: virtual Array getWrapperMetaData() { return null_array; } virtual const char *getStreamType() const { return "";} + std::string getMode() { return m_mode; } + /** * Read one line a time. Returns a null string on failure or eof. */ diff --git a/hphp/runtime/ext/ext_bzip2.cpp b/hphp/runtime/ext/ext_bzip2.cpp index 2896b0d7f..7c0b8fdf3 100644 --- a/hphp/runtime/ext/ext_bzip2.cpp +++ b/hphp/runtime/ext/ext_bzip2.cpp @@ -34,19 +34,64 @@ Variant f_bzwrite(CObjRef bz, CStrRef data, int length /* = 0 */) { return f_fwrite(bz, data, length); } -Variant f_bzopen(CStrRef filename, CStrRef mode) { +Variant f_bzopen(CVarRef filename, CStrRef mode) { if (mode != "r" && mode != "w") { + raise_warning( + "'%s' is not a valid mode for bzopen(). " + "Only 'w' and 'r' are supported.", + mode.data() + ); return false; } - BZ2File *bz = NEWOBJ(BZ2File)(); + BZ2File *bz; + if (filename.isString()) { + if (filename.asCStrRef().empty()) { + raise_warning("filename cannot be empty"); + return false; + } + bz = NEWOBJ(BZ2File)(); + bool ret = bz->open(File::TranslatePath(filename), mode); + if (!ret) { + raise_warning("%s", Util::safe_strerror(errno).c_str()); + return false; + } + } else { + if (!filename.isResource()) { + raise_warning("first parameter has to be string or file-resource"); + return false; + } + PlainFile* f = filename.cast(); + if (!f) { + return false; + } + + std::string stream_mode = f->getMode(); + int stream_mode_len = stream_mode.length(); + + if (stream_mode_len != 1 && + !(stream_mode_len == 2 && stream_mode.find('b') != string::npos)) { + raise_warning("cannot use stream opened in mode '%s'", stream_mode.c_str()); + return false; + } else if (stream_mode_len == 1 && + stream_mode[0] != 'r' && stream_mode[0] != 'w' && + stream_mode[0] != 'a' && stream_mode[0] != 'x') { + raise_warning("cannot use stream opened in mode '%s'", stream_mode.c_str()); + return false; + } + + const char rw_mode = stream_mode[0]; + if (mode == "r" && rw_mode != 'r') { + raise_warning("cannot write to a stream opened in read only mode"); + return false; + } else if (mode == "w" && rw_mode != 'w' && rw_mode != 'a' && rw_mode != 'x') { + raise_warning("cannot read from a stream opened in write only mode"); + return false; + } + + bz = NEWOBJ(BZ2File)(f); + } Object handle(bz); - - bool ret = bz->open(File::TranslatePath(filename), mode); - if (!ret) { - raise_warning("%s", Util::safe_strerror(errno).c_str()); - return false; - } return handle; } diff --git a/hphp/runtime/ext/ext_bzip2.ext_hhvm.cpp b/hphp/runtime/ext/ext_bzip2.ext_hhvm.cpp index f19fc0c88..facb08720 100644 --- a/hphp/runtime/ext/ext_bzip2.ext_hhvm.cpp +++ b/hphp/runtime/ext/ext_bzip2.ext_hhvm.cpp @@ -75,8 +75,8 @@ TypedValue* fg_bzclose(HPHP::VM::ActRec *ar) { /* -HPHP::Variant HPHP::f_bzopen(HPHP::String const&, HPHP::String const&) -_ZN4HPHP8f_bzopenERKNS_6StringES2_ +HPHP::Variant HPHP::f_bzopen(HPHP::Variant const&, HPHP::String const&) +_ZN4HPHP8f_bzopenERKNS_7VariantERKNS_6StringE (return value) => rax _rv => rdi @@ -84,18 +84,13 @@ filename => rsi mode => rdx */ -TypedValue* fh_bzopen(TypedValue* _rv, Value* filename, Value* mode) asm("_ZN4HPHP8f_bzopenERKNS_6StringES2_"); +TypedValue* fh_bzopen(TypedValue* _rv, TypedValue* filename, Value* mode) asm("_ZN4HPHP8f_bzopenERKNS_7VariantERKNS_6StringE"); TypedValue * fg1_bzopen(TypedValue* rv, HPHP::VM::ActRec* ar, int64_t count) __attribute__((noinline,cold)); TypedValue * fg1_bzopen(TypedValue* rv, HPHP::VM::ActRec* ar, int64_t count) { TypedValue* args UNUSED = ((TypedValue*)ar) - 1; - if (!IS_STRING_TYPE((args-1)->m_type)) { - tvCastToStringInPlace(args-1); - } - if (!IS_STRING_TYPE((args-0)->m_type)) { - tvCastToStringInPlace(args-0); - } - fh_bzopen((rv), &args[-0].m_data, &args[-1].m_data); + tvCastToStringInPlace(args-1); + fh_bzopen((rv), (args-0), &args[-1].m_data); if (rv->m_type == KindOfUninit) rv->m_type = KindOfNull; return rv; } @@ -105,8 +100,8 @@ TypedValue* fg_bzopen(HPHP::VM::ActRec *ar) { int64_t count = ar->numArgs(); TypedValue* args UNUSED = ((TypedValue*)ar) - 1; if (count == 2LL) { - if (IS_STRING_TYPE((args-1)->m_type) && IS_STRING_TYPE((args-0)->m_type)) { - fh_bzopen((&(rv)), &args[-0].m_data, &args[-1].m_data); + if (IS_STRING_TYPE((args-1)->m_type)) { + fh_bzopen((&(rv)), (args-0), &args[-1].m_data); if (rv.m_type == KindOfUninit) rv.m_type = KindOfNull; frame_free_locals_no_this_inl(ar, 2); memcpy(&ar->m_r, &rv, sizeof(TypedValue)); diff --git a/hphp/runtime/ext/ext_bzip2.ext_hhvm.h b/hphp/runtime/ext/ext_bzip2.ext_hhvm.h index 2367d5db0..5e699d50a 100644 --- a/hphp/runtime/ext/ext_bzip2.ext_hhvm.h +++ b/hphp/runtime/ext/ext_bzip2.ext_hhvm.h @@ -28,8 +28,8 @@ bz => rsi TypedValue* fh_bzclose(TypedValue* _rv, Value* bz) asm("_ZN4HPHP9f_bzcloseERKNS_6ObjectE"); /* -HPHP::Variant HPHP::f_bzopen(HPHP::String const&, HPHP::String const&) -_ZN4HPHP8f_bzopenERKNS_6StringES2_ +HPHP::Variant HPHP::f_bzopen(HPHP::Variant const&, HPHP::String const&) +_ZN4HPHP8f_bzopenERKNS_7VariantERKNS_6StringE (return value) => rax _rv => rdi @@ -37,7 +37,7 @@ filename => rsi mode => rdx */ -TypedValue* fh_bzopen(TypedValue* _rv, Value* filename, Value* mode) asm("_ZN4HPHP8f_bzopenERKNS_6StringES2_"); +TypedValue* fh_bzopen(TypedValue* _rv, TypedValue* filename, Value* mode) asm("_ZN4HPHP8f_bzopenERKNS_7VariantERKNS_6StringE"); /* HPHP::Variant HPHP::f_bzread(HPHP::Object const&, int) diff --git a/hphp/runtime/ext/ext_bzip2.h b/hphp/runtime/ext/ext_bzip2.h index 8590b2a97..1c9539122 100644 --- a/hphp/runtime/ext/ext_bzip2.h +++ b/hphp/runtime/ext/ext_bzip2.h @@ -30,7 +30,7 @@ Variant f_bzclose(CObjRef bz); Variant f_bzread(CObjRef bz, int length = 1024); Variant f_bzwrite(CObjRef bz, CStrRef data, int length = 0); -Variant f_bzopen(CStrRef filename, CStrRef mode); +Variant f_bzopen(CVarRef filename, CStrRef mode); Variant f_bzflush(CObjRef bz); String f_bzerrstr(CObjRef bz); Variant f_bzerror(CObjRef bz); diff --git a/hphp/system/class_map.cpp b/hphp/system/class_map.cpp index 564b62ac9..14f6c0e88 100644 --- a/hphp/system/class_map.cpp +++ b/hphp/system/class_map.cpp @@ -12363,8 +12363,8 @@ const char *g_class_map[] = { NULL, NULL, (const char *)0x10006040, "bzopen", "", (const char*)0, (const char*)0, - "/**\n * ( excerpt from http://php.net/manual/en/function.bzopen.php )\n *\n * bzopen() opens a bzip2 (.bz2) file for reading or writing.\n *\n * @filename string The name of the file to open.\n * @mode string Similar to the fopen() function, only 'r' (read) and\n * 'w' (write) are supported. Everything else will\n * cause bzopen to return FALSE.\n *\n * @return mixed If the open fails, bzopen() returns FALSE, otherwise\n * it returns a pointer to the newly opened file.\n */", - (const char *)0xffffffff /* KindOfUnknown: $t: Variant */, (const char *)0x2000, "filename", "", (const char *)0x14 /* KindOfString */, "", (const char *)0, "", (const char *)0, NULL, + "/**\n * ( excerpt from http://php.net/manual/en/function.bzopen.php )\n *\n * bzopen() opens a bzip2 (.bz2) file for reading or writing.\n *\n * @filename mixed The name of the file to open.\n * @mode string Similar to the fopen() function, only 'r' (read) and\n * 'w' (write) are supported. Everything else will\n * cause bzopen to return FALSE.\n *\n * @return mixed If the open fails, bzopen() returns FALSE, otherwise\n * it returns a pointer to the newly opened file.\n */", + (const char *)0xffffffff /* KindOfUnknown: $t: Variant */, (const char *)0x2000, "filename", "", (const char *)0xffffffff /* KindOfUnknown: $t: Variant */, "", (const char *)0, "", (const char *)0, NULL, (const char *)0x2000, "mode", "", (const char *)0x14 /* KindOfString */, "", (const char *)0, "", (const char *)0, NULL, NULL, NULL, diff --git a/hphp/test/zend/bad/ext-bz2/003.php b/hphp/test/zend/bad/ext-bz2/003.php new file mode 100644 index 000000000..45512b0cb --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/003.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/003.php.expectf b/hphp/test/zend/bad/ext-bz2/003.php.expectf new file mode 100644 index 000000000..3fae11e98 --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/003.php.expectf @@ -0,0 +1,19 @@ +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +string(0) "" +HipHop Warning: %a +bool(false) +string(1) "R" +string(2) "is" +string(251) "ing up from the heart of the desert +Rising up for Jerusalem +Rising up from the heat of the desert +Building up Old Jerusalem +Rising up from the heart of the desert +Rising up for Jerusalem +Rising up from the heat of the desert +Heading out for Jerusalem +" +Done \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/004.php b/hphp/test/zend/bad/ext-bz2/004.php new file mode 100644 index 000000000..68868a65e --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/004.php @@ -0,0 +1,40 @@ + \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/004.php.expectf b/hphp/test/zend/bad/ext-bz2/004.php.expectf new file mode 100644 index 000000000..a1f36f064 --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/004.php.expectf @@ -0,0 +1,61 @@ +array(2) { + ["errno"]=> + int(0) + ["errstr"]=> + string(2) "OK" +} +string(2) "OK" +int(0) +array(2) { + ["errno"]=> + int(0) + ["errstr"]=> + string(2) "OK" +} +string(2) "OK" +int(0) +string(0) "" +array(2) { + ["errno"]=> + int(-5) + ["errstr"]=> + string(16) "DATA_ERROR_MAGIC" +} +string(16) "DATA_ERROR_MAGIC" +int(-5) +string(0) "" +array(2) { + ["errno"]=> + int(-4) + ["errstr"]=> + string(10) "DATA_ERROR" +} +string(10) "DATA_ERROR" +int(-4) +string(0) "" +array(2) { + ["errno"]=> + int(-5) + ["errstr"]=> + string(16) "DATA_ERROR_MAGIC" +} +string(16) "DATA_ERROR_MAGIC" +int(-5) +string(0) "" +array(2) { + ["errno"]=> + int(-4) + ["errstr"]=> + string(10) "DATA_ERROR" +} +string(10) "DATA_ERROR" +int(-4) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +Done \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/005.php b/hphp/test/zend/bad/ext-bz2/005.php new file mode 100644 index 000000000..471d8b1b4 --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/005.php @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/005.php.expectf b/hphp/test/zend/bad/ext-bz2/005.php.expectf new file mode 100644 index 000000000..c10f6ce93 --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/005.php.expectf @@ -0,0 +1,29 @@ +HipHop Warning: %a +NULL +string(%d) "BZ%a" +int(-2) +int(-2) +int(-2) +int(-2) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +int(-5) +int(-5) +int(-5) +bool(false) +string(110) "Life it seems, will fade away +Drifting further everyday +Getting lost within myself +Nothing matters no one else" +bool(false) +string(110) "Life it seems, will fade away +Drifting further everyday +Getting lost within myself +Nothing matters no one else" +string(110) "Life it seems, will fade away +Drifting further everyday +Getting lost within myself +Nothing matters no one else" +Done \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/bz2_filter_compress.php b/hphp/test/zend/bad/ext-bz2/bz2_filter_compress.php new file mode 100644 index 000000000..e58cd043d --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/bz2_filter_compress.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/bz2_filter_compress.php.expectf b/hphp/test/zend/bad/ext-bz2/bz2_filter_compress.php.expectf new file mode 100644 index 000000000..40836001b --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/bz2_filter_compress.php.expectf @@ -0,0 +1 @@ +QlpoNDFBWSZTWRN6QG0AAAoVgECFACA395UgIABIintI1N6mpowIQ0E1MTTAQGYTNcRyMZm5kgW3ib7hVboE7Tmqj3ToGZ5G3q1ZauD2G58hibSck8KS95EEAbx1Cn+LuSKcKEgJvSA2gA== \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/bz2_filter_decompress.php b/hphp/test/zend/bad/ext-bz2/bz2_filter_decompress.php new file mode 100644 index 000000000..22a0bfce9 --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/bz2_filter_decompress.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/bz2_filter_decompress.php.expectf b/hphp/test/zend/bad/ext-bz2/bz2_filter_decompress.php.expectf new file mode 100644 index 000000000..0024eccac --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/bz2_filter_decompress.php.expectf @@ -0,0 +1 @@ +I am the very model of a modern major general, I've information vegetable, animal, and mineral. \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-bz2/with_strings.php b/hphp/test/zend/bad/ext-bz2/with_strings.php new file mode 100644 index 000000000..ccc1c3b04 --- /dev/null +++ b/hphp/test/zend/bad/ext-bz2/with_strings.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/hphp/test/zend/good/ext-bz2/001.php.expectf b/hphp/test/zend/good/ext-bz2/001.php.expectf new file mode 100644 index 000000000..114533a6e --- /dev/null +++ b/hphp/test/zend/good/ext-bz2/001.php.expectf @@ -0,0 +1,16 @@ +HipHop Warning: %a +NULL +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +resource(%d) of type (stream) +Done \ No newline at end of file diff --git a/hphp/test/zend/good/ext-bz2/002.php b/hphp/test/zend/good/ext-bz2/002.php new file mode 100644 index 000000000..0b9e606c7 --- /dev/null +++ b/hphp/test/zend/good/ext-bz2/002.php @@ -0,0 +1,70 @@ + \ No newline at end of file diff --git a/hphp/test/zend/good/ext-bz2/002.php.expectf b/hphp/test/zend/good/ext-bz2/002.php.expectf new file mode 100644 index 000000000..4cdd3032c --- /dev/null +++ b/hphp/test/zend/good/ext-bz2/002.php.expectf @@ -0,0 +1,37 @@ +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) +HipHop Warning: %a +bool(false) +resource(%d) of type (stream) +resource(%d) of type (stream) +HipHop Warning: %a +HipHop Warning: %a +bool(false) +HipHop Warning: %a +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +HipHop Warning: %a +bool(false) +resource(%d) of type (stream) +Done \ No newline at end of file diff --git a/hphp/test/zend/good/ext-bz2/bug51997.php b/hphp/test/zend/good/ext-bz2/bug51997.php new file mode 100644 index 000000000..6e5f85170 --- /dev/null +++ b/hphp/test/zend/good/ext-bz2/bug51997.php @@ -0,0 +1,16 @@ +