int main(int argc, char **argv)
{
  ScopedXPCOM xpcom("TestMimeCrash");
  if (xpcom.failed())
    return 1;

  // We cannot use malloc() since this crashes depends on memory allocation.
  // By using mmap()/PR_MemMap(), end of buffer that is last in the page
  // sets LF.

  PRUint32 bufsize = PR_GetPageSize();
  PRFileMap *fm = PR_OpenAnonFileMap(".", bufsize, PR_PROT_READWRITE);
  if (!fm)
    return 1;
  char *addr = (char *) PR_MemMap(fm, 0, bufsize);
  if (!addr)
    return 1;
  memset(addr, '\r', bufsize);

  nsresult rv = do_test(addr, bufsize);

  PR_MemUnmap(addr, bufsize);
  PR_CloseFileMap(fm);

  if (NS_FAILED(rv)) {
    fail("cannot use nsIMimeConverter error=%08x\n", rv);
    return -1;
  }

  passed("no crash");

  return 0;
}
Exemple #2
0
nsresult
AutoMemMap::init(const char* filePath, int flags, int mode, PRFileMapProtect prot)
{
  MOZ_ASSERT(!fd);
  MOZ_ASSERT(!fileMap);
  MOZ_ASSERT(!addr);

  if (PR_GetFileInfo64(filePath, &fileInfo) != PR_SUCCESS)
    return NS_ERROR_FILE_NOT_FOUND;

  // Check if the file is too big to memmap.
  if (fileInfo.size > int64_t(UINT32_MAX))
    return NS_ERROR_INVALID_ARG;
  auto length = uint32_t(fileInfo.size);

  fd = PR_Open(filePath, flags, flags);
  if (!fd)
    return NS_ERROR_UNEXPECTED;

  fileMap = PR_CreateFileMap(fd, fileInfo.size, prot);
  if (!fileMap)
    return NS_ERROR_UNEXPECTED;

  addr = PR_MemMap(fileMap, 0, length);
  if (!addr)
    return NS_ERROR_UNEXPECTED;

  return NS_OK;
}
Exemple #3
0
PRStatus FastFetchFile(PRFileDesc *in, PRFileDesc *out, PRUint32 size)
{
    PRInt32 nBytes;
    PRFileMap *outfMap;
    void *addr;
    char *start;
    PRUint32 rem;
    PRUint32 bytesToRead;
    PRStatus rv;
    PRInt64 sz64;

    LL_UI2L(sz64, size);
    outfMap = PR_CreateFileMap(out, sz64, PR_PROT_READWRITE);
    PR_ASSERT(outfMap);
    addr = PR_MemMap(outfMap, LL_ZERO, size);
    if (addr == (void *) -1) {
	fprintf(stderr, "cannot memory-map file: (%d, %d)\n", PR_GetError(),
		PR_GetOSError());

	PR_CloseFileMap(outfMap);
	return PR_FAILURE;
    }
    PR_ASSERT(addr != (void *) -1);
    start = (char *) addr;
    rem = size;
    while ((nBytes = DrainInputBuffer(start, rem)) > 0) {
	start += nBytes;
	rem -= nBytes;
    }
    if (nBytes < 0) {
	/* Input buffer is empty and end of stream */
	return PR_SUCCESS;
    }
    bytesToRead = (rem < FCOPY_BUFFER_SIZE) ? rem : FCOPY_BUFFER_SIZE;
    while (rem > 0 && (nBytes = PR_Read(in, start, bytesToRead)) > 0) {
	start += nBytes;
	rem -= nBytes;
        bytesToRead = (rem < FCOPY_BUFFER_SIZE) ? rem : FCOPY_BUFFER_SIZE;
    }
    if (nBytes < 0) {
	fprintf(stderr, "httpget: cannot read from socket\n");
	return PR_FAILURE;
    }
    rv = PR_MemUnmap(addr, size);
    PR_ASSERT(rv == PR_SUCCESS);
    rv = PR_CloseFileMap(outfMap);
    PR_ASSERT(rv == PR_SUCCESS);
    return PR_SUCCESS;
}
nsresult
mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponent,
                                        JSObject **aGlobal,
                                        char **aLocation)
{
    nsresult rv;

    JSPrincipals* jsPrincipals = nsnull;
    JSCLContextHelper cx(mContext);

#ifndef XPCONNECT_STANDALONE
    rv = mSystemPrincipal->GetJSPrincipals(cx, &jsPrincipals);
    NS_ENSURE_SUCCESS(rv, rv);

    JSPrincipalsHolder princHolder(mContext, jsPrincipals);
#endif

    nsCOMPtr<nsIXPCScriptable> backstagePass;
    rv = mRuntimeService->GetBackstagePass(getter_AddRefs(backstagePass));
    NS_ENSURE_SUCCESS(rv, rv);

    JSCLAutoErrorReporterSetter aers(cx, mozJSLoaderErrorReporter);

    nsCOMPtr<nsIXPConnect> xpc =
        do_GetService(kXPConnectServiceContractID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    // Make sure InitClassesWithNewWrappedGlobal() installs the
    // backstage pass as the global in our compilation context.
    JS_SetGlobalObject(cx, nsnull);

    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
    rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
                                              NS_GET_IID(nsISupports),
                                              nsIXPConnect::
                                                  FLAG_SYSTEM_GLOBAL_OBJECT,
                                              getter_AddRefs(holder));
    NS_ENSURE_SUCCESS(rv, rv);

    JSObject *global;
    rv = holder->GetJSObject(&global);
    NS_ENSURE_SUCCESS(rv, rv);

    if (!JS_DefineFunctions(cx, global, gGlobalFun)) {
        return NS_ERROR_FAILURE;
    }

    nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
    rv = xpc->WrapNative(cx, global, aComponent,
                         NS_GET_IID(nsILocalFile),
                         getter_AddRefs(locationHolder));
    NS_ENSURE_SUCCESS(rv, rv);

    JSObject *locationObj;
    rv = locationHolder->GetJSObject(&locationObj);
    NS_ENSURE_SUCCESS(rv, rv);

    if (!JS_DefineProperty(cx, global, "__LOCATION__",
                           OBJECT_TO_JSVAL(locationObj), nsnull, nsnull, 0)) {
        return NS_ERROR_FAILURE;
    }

    nsCAutoString nativePath;
    // Quick hack to unbust XPCONNECT_STANDALONE.
    // This leaves the jsdebugger with a non-URL pathname in the 
    // XPCONNECT_STANDALONE case - but at least it builds and runs otherwise.
    // See: http://bugzilla.mozilla.org/show_bug.cgi?id=121438
#ifdef XPCONNECT_STANDALONE
    localFile->GetNativePath(nativePath);
#else
    NS_GetURLSpecFromFile(aComponent, nativePath);
#endif

    // Before compiling the script, first check to see if we have it in
    // the fastload file.  Note: as a rule, fastload errors are not fatal
    // to loading the script, since we can always slow-load.
    nsCOMPtr<nsIFastLoadService> flSvc = do_GetFastLoadService(&rv);

    // Save the old state and restore it upon return
    FastLoadStateHolder flState(flSvc);
    PRBool fastLoading = PR_FALSE;

    if (NS_SUCCEEDED(rv)) {
        rv = StartFastLoad(flSvc);
        if (NS_SUCCEEDED(rv)) {
            fastLoading = PR_TRUE;
        }
    }

    nsCOMPtr<nsIURI> uri;
    rv = NS_NewURI(getter_AddRefs(uri), nativePath);
    NS_ENSURE_SUCCESS(rv, rv);

    JSScript *script = nsnull;

    if (fastLoading) {
        rv = ReadScript(flSvc, nativePath.get(), uri, cx, &script);
        if (NS_SUCCEEDED(rv)) {
            LOG(("Successfully loaded %s from fastload\n", nativePath.get()));
            fastLoading = PR_FALSE; // no need to write out the script
        } else if (rv == NS_ERROR_NOT_AVAILABLE) {
            // This is ok, it just means the script is not yet in the
            // fastload file.
            rv = NS_OK;
        } else {
            LOG(("Failed to deserialize %s\n", nativePath.get()));

            // Remove the fastload file, it may be corrupted.
            LOG(("Invalid fastload file detected, removing it\n"));
            nsCOMPtr<nsIObjectOutputStream> objectOutput;
            flSvc->GetOutputStream(getter_AddRefs(objectOutput));
            if (objectOutput) {
                flSvc->SetOutputStream(nsnull);
                objectOutput->Close();
            }
            nsCOMPtr<nsIObjectInputStream> objectInput;
            flSvc->GetInputStream(getter_AddRefs(objectInput));
            if (objectInput) {
                flSvc->SetInputStream(nsnull);
                objectInput->Close();
            }
            if (mFastLoadFile) {
                mFastLoadFile->Remove(PR_FALSE);
            }
            fastLoading = PR_FALSE;
        }
    }


    if (!script || NS_FAILED(rv)) {
        // The script wasn't in the fastload cache, so compile it now.
        LOG(("Slow loading %s\n", nativePath.get()));

#ifdef HAVE_PR_MEMMAP
        PRInt64 fileSize;
        rv = aComponent->GetFileSize(&fileSize);
        if (NS_FAILED(rv))
            return rv;

        PRInt64 maxSize;
        LL_UI2L(maxSize, PR_UINT32_MAX);
        if (LL_CMP(fileSize, >, maxSize)) {
            NS_ERROR("file too large");
            return NS_ERROR_FAILURE;
        }

        PRFileDesc *fileHandle;
        rv = aComponent->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
        NS_ENSURE_SUCCESS(rv, rv);

        // Make sure the file is closed, no matter how we return.
        FileAutoCloser fileCloser(fileHandle);

        PRFileMap *map = PR_CreateFileMap(fileHandle, fileSize,
                                          PR_PROT_READONLY);
        if (!map) {
            NS_ERROR("Failed to create file map");
            return NS_ERROR_FAILURE;
        }

        // Make sure the file map is closed, no matter how we return.
        FileMapAutoCloser mapCloser(map);

        PRUint32 fileSize32;
        LL_L2UI(fileSize32, fileSize);

        char *buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32));
        if (!buf) {
            NS_WARNING("Failed to map file");
            return NS_ERROR_FAILURE;
        }

        script = JS_CompileScriptForPrincipals(cx, global,
                                               jsPrincipals,
                                               buf, fileSize32,
                                               nativePath.get(), 1);
        PR_MemUnmap(buf, fileSize32);

#else  /* HAVE_PR_MEMMAP */

        /**
         * No memmap implementation, so fall back to using
         * JS_CompileFileHandleForPrincipals().
         */

        FILE *fileHandle;
        rv = aComponent->OpenANSIFileDesc("r", &fileHandle);
        NS_ENSURE_SUCCESS(rv, rv);

        script = JS_CompileFileHandleForPrincipals(cx, global,
                                                   nativePath.get(),
                                                   fileHandle, jsPrincipals);

        /* JS will close the filehandle after compilation is complete. */

#endif /* HAVE_PR_MEMMAP */
    }
Exemple #5
0
PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
    PRFileDesc *sd, PRSendFileData *sfd,
    PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    PRInt32 rv, count = 0;
    PRInt32 len, file_bytes, index = 0;
    PRFileInfo info;
    PRIOVec iov[3];
    PRFileMap *mapHandle = NULL;
    void *addr = (void*)0; /* initialized to some arbitrary value. Keeps compiler warnings down. */
    PRUint32 file_mmap_offset, alignment;
    PRInt64 zero64;
    PROffset64 file_mmap_offset64;
    PRUint32 addr_offset, mmap_len;

    /* Get file size */
    if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) {
        count = -1;
        goto done;
    }
    if (sfd->file_nbytes &&
            (info.size < (sfd->file_offset + sfd->file_nbytes))) {
        /*
         * there are fewer bytes in file to send than specified
         */
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        count = -1;
        goto done;
    }
    if (sfd->file_nbytes)
        file_bytes = sfd->file_nbytes;
    else
        file_bytes = info.size - sfd->file_offset;

    alignment = PR_GetMemMapAlignment();

    /* number of initial bytes to skip in mmap'd segment */
    addr_offset = sfd->file_offset % alignment;

    /* find previous mmap alignment boundary */
    file_mmap_offset = sfd->file_offset - addr_offset;

    /*
     * If the file is large, mmap and send the file in chunks so as
     * to not consume too much virtual address space
     */
    mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK);
    len = mmap_len - addr_offset;

    /*
     * Map in (part of) file. Take care of zero-length files.
     */
    if (len) {
        LL_I2L(zero64, 0);
        mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY);
        if (!mapHandle) {
            count = -1;
            goto done;
        }
        LL_I2L(file_mmap_offset64, file_mmap_offset);
        addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len);
        if (!addr) {
            count = -1;
            goto done;
        }
    }
    /*
     * send headers first, followed by the file
     */
    if (sfd->hlen) {
        iov[index].iov_base = (char *) sfd->header;
        iov[index].iov_len = sfd->hlen;
        index++;
    }
    if (len) {
        iov[index].iov_base = (char*)addr + addr_offset;
        iov[index].iov_len = len;
        index++;
    }
    if ((file_bytes == len) && (sfd->tlen)) {
        /*
         * all file data is mapped in; send the trailer too
         */
        iov[index].iov_base = (char *) sfd->trailer;
        iov[index].iov_len = sfd->tlen;
        index++;
    }
    rv = PR_Writev(sd, iov, index, timeout);
    if (len)
        PR_MemUnmap(addr, mmap_len);
    if (rv < 0) {
        count = -1;
        goto done;
    }

    PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0));

    file_bytes -= len;
    count += rv;
    if (!file_bytes)    /* header, file and trailer are sent */
        goto done;

    /*
     * send remaining bytes of the file, if any
     */
    len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
    while (len > 0) {
        /*
         * Map in (part of) file
         */
        file_mmap_offset = sfd->file_offset + count - sfd->hlen;
        PR_ASSERT((file_mmap_offset % alignment) == 0);

        LL_I2L(file_mmap_offset64, file_mmap_offset);
        addr = PR_MemMap(mapHandle, file_mmap_offset64, len);
        if (!addr) {
            count = -1;
            goto done;
        }
        rv = PR_Send(sd, addr, len, 0, timeout);
        PR_MemUnmap(addr, len);
        if (rv < 0) {
            count = -1;
            goto done;
        }

        PR_ASSERT(rv == len);
        file_bytes -= rv;
        count += rv;
        len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
    }
    PR_ASSERT(0 == file_bytes);
    if (sfd->tlen) {
        rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
        if (rv >= 0) {
            PR_ASSERT(rv == sfd->tlen);
            count += rv;
        } else
            count = -1;
    }
done:
    if (mapHandle)
        PR_CloseFileMap(mapHandle);
    if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
        PR_Close(sd);
    return count;
}