Пример #1
0
bool GetCallMemoryCopy(PEdgeCall *edge, Exp **target,
                       Exp **source, Exp **length)
{
  Variable *name = edge->GetDirectFunction();

  if (!name)
    return false;

  MemcpyFunctionInfo *cur_memcpy = g_memcpy_functions;
  while (cur_memcpy->name) {
    if (TextNameMatch(name, cur_memcpy->name)) {
      *target = GetArgumentValue(cur_memcpy->target_arg);
      *source = GetArgumentValue(cur_memcpy->source_arg);
      *length = GetArgumentValue(cur_memcpy->length_arg);
      return true;
    }

    cur_memcpy++;
  }

  ReallocFunctionInfo *cur_realloc = g_realloc_functions;
  while (cur_realloc->name) {
    if (TextNameMatch(name, cur_realloc->name)) {
      *target = GetReturnedValue();
      *source = GetArgumentValue(cur_realloc->base_arg);
      (*source)->IncRef();
      *length = GetByteUpperBound(*source);
      return true;
    }

    cur_realloc++;
  }

  return false;
}
Пример #2
0
bool GetAllocationFunction(Variable *name, Exp **object, Exp **size)
{
  MallocFunctionInfo *cur_malloc = g_malloc_functions;
  while (cur_malloc->name) {
    if (TextNameMatch(name, cur_malloc->name)) {
      *object = GetReturnedValue();
      *size = GetArgumentValue(cur_malloc->size_arg);
      return true;
    }

    cur_malloc++;
  }

  FixedMallocFunctionInfo *cur_fixed = g_fixed_malloc_functions;
  while (cur_fixed->name) {
    if (TextNameMatch(name, cur_fixed->name)) {
      *object = GetReturnedValue();
      *size = Exp::MakeInt(cur_fixed->size);
      return true;
    }

    cur_fixed++; 
  }

  CallocFunctionInfo *cur_calloc = g_calloc_functions;
  while (cur_calloc->name) {
    if (TextNameMatch(name, cur_calloc->name)) {
      Exp *size_one = GetArgumentValue(cur_calloc->size_arg_one);
      Exp *size_two = GetArgumentValue(cur_calloc->size_arg_two);
      *object = GetReturnedValue();
      *size = Exp::MakeBinop(cur_calloc->binop, size_one, size_two);
      return true;
    }

    cur_calloc++;
  }

  return false;
}
Пример #3
0
/* virtual */
OP_STATUS
ES_JavascriptURLThread::EvaluateThread()
{
	OP_STATUS ret = OpStatus::OK;

	switch (eval_state)
	{
	case STATE_INITIAL:
		{
			eval_state = STATE_SET_PROGRAM;

#ifdef USER_JAVASCRIPT
			DOM_Environment *environment = scheduler->GetFramesDocument()->GetDOMEnvironment();

			RETURN_IF_ERROR(environment->HandleJavascriptURL(this));

			if (IsBlocked())
				return OpStatus::OK;
#endif // USER_JAVASCRIPT
		}
		// fall through

	case STATE_SET_PROGRAM:
		if (source)
		{
			ES_ProgramText program_text;

			program_text.program_text = source;
			program_text.program_text_length = uni_strlen(source);

			ES_Runtime *runtime = scheduler->GetRuntime();

			ES_Program *program;
			OP_STATUS status;

			ES_Runtime::CompileProgramOptions options;
			options.generate_result = TRUE;
			options.global_scope = FALSE;
			options.script_type = SCRIPT_TYPE_JAVASCRIPT_URL;
			options.when = UNI_L("while loading");
			options.script_url = &url;
#ifdef ECMASCRIPT_DEBUGGER
			options.reformat_source = g_ecmaManager->GetWantReformatScript(runtime);
#endif // ECMASCRIPT_DEBUGGER

			if (OpStatus::IsSuccess(status = runtime->CompileProgram(&program_text, 1, &program, options)))
				if (program)
					SetProgram(program);
				else
					status = OpStatus::ERR;

			if (OpStatus::IsMemoryError(status))
			{
				is_completed = is_failed = TRUE;
				return status;
			}
			else if (OpStatus::IsError(status))
			{
				is_completed = is_failed = TRUE;
				return OpStatus::OK;
			}
		}
		eval_state = STATE_EVALUATE;
		// fall through

	case STATE_EVALUATE:
		{
			ret = ES_Thread::EvaluateThread();
			if (OpStatus::IsError(ret))
			{
				eval_state = STATE_HANDLE_RESULT;
				is_completed = TRUE;
				break;
			}
			else if (IsCompleted())
			{
				if (IsFailed())
				{
					eval_state = STATE_DONE;
					break;
				}
				else
#ifdef USER_JAVASCRIPT
					eval_state = STATE_SEND_USER_JS_AFTER;
#else // USER_JAVASCRIPT
					eval_state = STATE_HANDLE_RESULT;
#endif // USER_JAVASCRIPT
			}
			else
				break;
		}
		// fall through

#ifdef USER_JAVASCRIPT
	case STATE_SEND_USER_JS_AFTER:
		{
			DOM_Environment *environment = scheduler->GetFramesDocument()->GetDOMEnvironment();

			RETURN_IF_ERROR(environment->HandleJavascriptURLFinished(this));

			eval_state = STATE_HANDLE_RESULT;

			if (IsBlocked())
			{
				is_completed = FALSE;
				break;
			}
		}
		// fall through
#endif // USER_JAVASCRIPT

	case STATE_HANDLE_RESULT:
		{
			is_completed = TRUE;
			const uni_char *use_result = NULL;

#ifdef USER_JAVASCRIPT
			if (has_result)
				use_result = result;
			else
#endif // USER_JAVASCRIPT
				if (ReturnedValue())
				{
					ES_Value return_value;

					RETURN_IF_ERROR(GetReturnedValue(&return_value));

					if (return_value.type == VALUE_STRING)
						use_result = return_value.value.string;
				}

			FramesDocument *frames_doc = GetFramesDocument();
			OP_ASSERT(frames_doc); // Since we're executing we must be in a document
			if (use_result)
			{
				if (write_result_to_document)
				{
					// The HTML5 spec says that we should load this data exactly as if it had come
					// from an HTTP connection with content type text/html and status 200. This
					// is a very bad approximation of that.
					BOOL is_busy = scheduler->IsDraining() || !frames_doc->IsCurrentDoc();
					write_result_to_document = FALSE; // Since it's enough to do it once
					frames_doc->SetWaitForJavascriptURL(FALSE);

					if (!is_busy)
						if (HLDocProfile *hld_profile = frames_doc->GetHLDocProfile())
							is_busy = hld_profile->GetESLoadManager()->GetScriptGeneratingDoc();

					if (!is_busy)
					{
						if (GetOriginInfo().open_in_new_window)
							RETURN_IF_ERROR(DOM_Environment::OpenWindowWithData(use_result, frames_doc, this, GetOriginInfo().is_user_requested));
						else
						{
							// The ESOpen()/ESClose() calls are just done in order to create an
							// empty document in The Right Way(tm) in order to parse some data
							// into it as if it had been loaded from a URL, and not to set up
							// a document.write call like they are usually used for.
							ESDocException doc_exception; // Ignored
							RETURN_IF_ERROR(frames_doc->ESOpen(scheduler->GetRuntime(), &url, is_reload, NULL, NULL, &doc_exception));

							FramesDocument *new_frames_doc = frames_doc->GetDocManager()->GetCurrentDoc();
							RETURN_IF_ERROR(new_frames_doc->ESClose(scheduler->GetRuntime()));

							SetBlockType(ES_BLOCK_NONE);

							if (frames_doc != new_frames_doc)
								RETURN_IF_ERROR(new_frames_doc->GetLogicalDocument()->ParseHtmlFromString(use_result, uni_strlen(use_result), FALSE, FALSE, FALSE));
							else
								OP_ASSERT(!"ESOpen might have failed, but if it didn't then we're stuck with a hung thread in a document and nothing will work");

							new_frames_doc->ESStoppedGeneratingDocument();
						}
					}
				}

				if (write_result_to_url)
				{
					if (want_utf8)
					{
						UTF16toUTF8Converter converter;

						unsigned length = uni_strlen(use_result) * sizeof source[0], needed = converter.BytesNeeded(use_result, length);
						converter.Reset();

						char *data;
						if (needed < g_memory_manager->GetTempBufLen())
							data = (char *) g_memory_manager->GetTempBuf();
						else
							data = OP_NEWA(char, needed);

						if (!data)
						{
							ret = OpStatus::ERR_NO_MEMORY;
							break;
						}
						else
						{
							int read, written = converter.Convert(use_result, length, data, needed, &read);

							url.WriteDocumentData(URL::KNormal, data, written);
							url.WriteDocumentDataFinished();

							if (data != g_memory_manager->GetTempBuf())
								OP_DELETEA(data);
						}
					}
					else
					{
						url.WriteDocumentData(URL::KNormal, use_result, uni_strlen(use_result));
						url.WriteDocumentDataFinished();
					}
				}
			}
			else if (write_result_to_document)
			{
				// The HTML5 spec says this should be handled as a HTTP status 204, NO_CONTENT
				frames_doc->GetMessageHandler()->PostMessage(MSG_URL_LOADING_FAILED, url.Id(), DH_ERRSTR(SI,ERR_HTTP_NO_CONTENT));
				frames_doc->SetWaitForJavascriptURL(FALSE);
				write_result_to_document = FALSE; // Since it's done and we don't want to do it again.
			}

			eval_state = STATE_DONE;
		}
Пример #4
0
void FillBakedSummary(BlockSummary *sum)
{
  Variable *name = sum->GetId()->BaseVar();

  // primitive memory allocator.

  Exp *object;
  Exp *size;

  if (GetAllocationFunction(name, &object, &size)) {
    Exp *bound = GetByteUpperBound(object);

    // the upper bound is greater or equal to zero.
    bound->IncRef();
    Exp *zero = Exp::MakeInt(0);
    Bit *bound_nonneg = Exp::MakeCompareBit(B_GreaterEqual, bound, zero);
    sum->AddAssume(bound_nonneg);

    // the upper bound of the object is exactly equal to size.
    Bit *bound_equal = Exp::MakeCompareBit(B_Equal, bound, size);
    sum->AddAssume(bound_equal);

    // TODO: it would be nice to assert the offset is exactly equal
    // to zero for the UI; however, this can lead to spurious contradiction
    // if unaligned pointers are in use.
  }

  // return value bears some relation with an argument.

  ReturnCompareFunctionInfo *cur_return = g_return_compare_functions;
  while (cur_return->name) {
    if (TextNameMatch(name, cur_return->name)) {
      Exp *ret_exp = GetReturnedValue();
      Exp *arg_exp = GetArgumentValue(cur_return->compare_arg);

      Type *type = NULL;
      if (IsPointerBinop(cur_return->binop))
        type = Type::MakeInt(1, true);

      Bit *bit = Exp::MakeCompareBit(cur_return->binop,
                                     ret_exp, arg_exp, type);
      sum->AddAssume(bit);
    }

    cur_return++;
  }

  // return value is NULL terminated.

  const char **cur_ret_term = g_return_terminated_functions;
  while (*cur_ret_term) {
    if (TextNameMatch(name, *cur_ret_term)) {
      Exp *ret_exp = GetReturnedValue();
      Exp *terminate = GetNullTerminate(ret_exp);
      Exp *zero = Exp::MakeInt(0);

      Bit *bit = Exp::MakeCompareBit(B_GreaterEqual, terminate, zero);
      sum->AddAssume(bit);
    }

    cur_ret_term++;
  }

  // an argument is NULL terminated.

  TerminateFunctionInfo *cur_term = g_terminate_functions;
  while (cur_term->name) {
    if (TextNameMatch(name, cur_term->name) && cur_term->terminates) {
      Exp *arg_exp = GetArgumentValue(cur_term->terminate_arg);
      Exp *kind = GetNullTerminate(NULL);
      Exp *exit_term = Exp::MakeExit(arg_exp, kind);
      Exp *zero = Exp::MakeInt(0);

      Bit *bit = Exp::MakeCompareBit(B_GreaterEqual, exit_term, zero);
      sum->AddAssume(bit);
    }

    cur_term++;
  }

  // strchr constraint: char_arg != 0 => zterm(ret) > 0.

  StrchrFunctionInfo *cur_strchr = g_strchr_functions;
  while (cur_strchr->name) {
    if (TextNameMatch(name, cur_strchr->name)) {
      Exp *arg_exp = GetArgumentValue(cur_strchr->char_arg);
      Exp *ret_exp = GetReturnedValue();
      Exp *terminate = GetNullTerminate(ret_exp);

      Exp *zero = Exp::MakeInt(0);
      zero->IncRef();

      Bit *left = Exp::MakeCompareBit(B_NotEqual, arg_exp, zero);
      Bit *right = Exp::MakeCompareBit(B_GreaterThan, terminate, zero);
      Bit *bit = Bit::MakeImply(left, right);
      sum->AddAssume(bit);
    }

    cur_strchr++;
  }

  // strlen constraint: ret >= 0 && ret == zterm(arg)

  StrlenFunctionInfo *cur_strlen = g_strlen_functions;
  while (cur_strlen->name) {
    if (TextNameMatch(name, cur_strlen->name)) {
      Exp *arg_exp = GetArgumentValue(cur_strlen->string_arg);
      Exp *retval = GetReturnedValue();

      Exp *terminate = GetNullTerminate(arg_exp);

      retval->IncRef();
      Exp *zero = Exp::MakeInt(0);
      Bit *ge_zero = Exp::MakeCompareBit(B_GreaterEqual, retval, zero);
      sum->AddAssume(ge_zero);

      Bit *eq_term = Exp::MakeCompareBit(B_Equal, retval, terminate);
      sum->AddAssume(eq_term);
    }

    cur_strlen++;
  }

  // strcmp constraint: ret == 0 ==> zterm(arg_one) == zterm(arg_two)

  StrcmpFunctionInfo *cur_strcmp = g_strcmp_functions;
  while (cur_strcmp->name) {
    if (TextNameMatch(name, cur_strcmp->name)) {
      Exp *arg_one_exp = GetArgumentValue(cur_strcmp->string_arg_one);
      Exp *arg_two_exp = GetArgumentValue(cur_strcmp->string_arg_two);
      Exp *retval = GetReturnedValue();

      Exp *terminate_one = GetNullTerminate(arg_one_exp);
      Exp *terminate_two = GetNullTerminate(arg_two_exp);

      Exp *zero = Exp::MakeInt(0);

      Bit *left = Exp::MakeCompareBit(B_Equal, retval, zero);
      Bit *right = Exp::MakeCompareBit(B_Equal, terminate_one, terminate_two);
      Bit *bit = Bit::MakeImply(left, right);
      sum->AddAssume(bit);
    }

    cur_strcmp++;
  }

  // strncmp constraint: ret == 0 ==> (zterm(arg_one) == zterm(arg_two)
  //                                || (zterm(arg_one) >= length_arg &&
  //                                    zterm(arg_two) >= length_arg))

  StrncmpFunctionInfo *cur_strncmp = g_strncmp_functions;
  while (cur_strncmp->name) {
    if (TextNameMatch(name, cur_strncmp->name)) {
      Exp *arg_one_exp = GetArgumentValue(cur_strncmp->string_arg_one);
      Exp *arg_two_exp = GetArgumentValue(cur_strncmp->string_arg_two);
      Exp *length_exp = GetArgumentValue(cur_strncmp->length_arg);
      Exp *retval = GetReturnedValue();

      Exp *terminate_one = GetNullTerminate(arg_one_exp);
      Exp *terminate_two = GetNullTerminate(arg_two_exp);

      Exp *zero = Exp::MakeInt(0);
      terminate_one->IncRef();
      terminate_two->IncRef();
      length_exp->IncRef();

      Bit *left = Exp::MakeCompareBit(B_Equal, retval, zero);
      Bit *term_eq = Exp::MakeCompareBit(B_Equal, terminate_one, terminate_two);
      Bit *ge_one = Exp::MakeCompareBit(B_GreaterEqual, terminate_one, length_exp);
      Bit *ge_two = Exp::MakeCompareBit(B_GreaterEqual, terminate_two, length_exp);
      Bit *ge_both = Bit::MakeAnd(ge_one, ge_two);
      Bit *right = Bit::MakeOr(term_eq, ge_both);
      Bit *bit = Bit::MakeImply(left, right);
      sum->AddAssume(bit);
    }

    cur_strncmp++;
  }
}